home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / Ph 1.1.1 / Lib / utl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-29  |  90.7 KB  |  2,963 lines  |  [TEXT/MPS ]

  1. /*______________________________________________________________________
  2.  
  3.     utl.c - Utilities.
  4.     
  5.     Copyright © 1988-1991 Northwestern University.
  6.     
  7.     This module exports miscellaneous reusable utility routines.
  8. _____________________________________________________________________*/
  9.  
  10. #pragma load "precompile"
  11. #include "utl.h"
  12.  
  13.  
  14. #pragma segment utl
  15.  
  16. /*______________________________________________________________________
  17.  
  18.     Global Variables.
  19. _____________________________________________________________________*/
  20.  
  21. static SysEnvRec        TheWorld;        /* system environment record */
  22. static Boolean            GotSysEnviron = false;    
  23.                                                 /* true if sys environ has been
  24.                                                     gotten */
  25.     
  26.             
  27. static CursHandle     *CursArray;        /* ptr to array of cursor handles */
  28. static short             NumCurs;            /* number of cursors to rotate */
  29. static short             TickInterval;    /* number of ticks between rotations */
  30. static short             CurCurs;            /* index of current cursor */
  31. static long             LastTick;        /* tick count at loast rotation */
  32.  
  33. /* The following global variables are used by the MetFilter, 
  34.     utl_ModalDialog, utl_ModalDialogContinue, and utl_StopAlert functions */
  35.  
  36. static ModalFilterProcPtr    Filter;    /* dialog filter proc */
  37. static short            DefaultItem;    /* item number of default button */
  38. static short            CancelItem;        /* item number of cancel button */
  39. static CursHandle        IBeamHandle;    /* handle to IBeam cursor */
  40.  
  41. /*______________________________________________________________________
  42.  
  43.     GetSysEnvirons - Get System Environment.
  44.     
  45.     Exit:        global variable TheWorld = system environment record.
  46.                 global variable GotSysEnviron = true.
  47. _____________________________________________________________________*/
  48.  
  49. static void GetSysEnvirons (void)
  50.  
  51. {
  52.     if (!GotSysEnviron) {
  53.         (void) SysEnvirons(curSysEnvVers, &TheWorld);
  54.         GotSysEnviron = true;
  55.     }
  56. }
  57.  
  58. /*______________________________________________________________________
  59.  
  60.     MetaFilter - Dialog Filter Proc.
  61.     
  62.     Entry:    theDialog = pointer to dialog record.
  63.                 theEvent = pointer to event record.
  64.     
  65.     Exit:        if command-period or escape typed and CancelItem is non-zero:
  66.                     function result = true.
  67.                     itemHit = CancelItem.
  68.                 else if return or enter typed and DefaultItem is non-zero:
  69.                     function result = true.
  70.                     itemHit = DefaultItem.
  71.                 else if user specified a filterProc on the call to
  72.                 utl_StopAlert, utl_ModalDialog, or utl_ModalDialogContinue:
  73.                     user's filterProc called, function result and itemHit
  74.                     returned by user's filterProc.
  75.                 else:
  76.                     function result = false.
  77.                     itemHit = undefined.
  78.                     
  79.     This filter proc also takes care of flashing the default and cancel
  80.     buttons when they are selected via key presses, and changing the cursor
  81.     to an Ibeam over textedit fields.
  82. _____________________________________________________________________*/
  83.  
  84. static pascal Boolean MetaFilter (DialogPtr theDialog,
  85.     EventRecord *theEvent, short *itemHit)
  86.     
  87. {
  88.     Point                where;                    /* mouse loc */
  89.     short                numItems;                /* number of items in dialog */
  90.     Boolean            SetCursorToIBeam;        /* true if mouse is over textedit field */
  91.     short                i;                            /* loop index */
  92.     short                itemType;                /* item type */
  93.     Handle            item;                        /* handle to item */
  94.     Rect                box;                        /* item rectangle */
  95.     
  96.     SetPort(theDialog);
  97.     GetMouse(&where);
  98.     numItems = **(short**)(((DialogPeek)theDialog)->items) + 1;
  99.     SetCursorToIBeam = false;
  100.     for (i = 1; i <= numItems; i++) {
  101.         GetDItem(theDialog, i, &itemType, &item, &box);
  102.         if ((itemType & 0x7f) == editText && PtInRect(where, &box)) {
  103.             SetCursorToIBeam = true;
  104.             break;
  105.         }
  106.     }
  107.     SetCursor(SetCursorToIBeam ? *IBeamHandle : &qd.arrow);
  108.     if (theEvent->what != keyDown && theEvent->what != autoKey) {
  109.         if (Filter) {
  110.             return (*Filter)(theDialog, theEvent, itemHit);
  111.         } else {
  112.             return false;
  113.         }
  114.     } else if (*itemHit = utl_CheckSpecialDialogKey(theDialog, 
  115.         theEvent->message & charCodeMask, theEvent->modifiers, 
  116.         DefaultItem, CancelItem)) {
  117.         return true;
  118.     } else if (Filter) {
  119.         return (*Filter)(theDialog, theEvent, itemHit);
  120.     } else {
  121.         return false;
  122.     }
  123. }
  124.  
  125. /*______________________________________________________________________
  126.  
  127.     MagicAlert - Present a Magic Alert.
  128.     
  129.     Entry:    tmpl = error message template.
  130.                 dlogID = resource id of error message dialog.
  131.                 filterProc = pointer to filter proc.
  132.                 p0,p1,p2,p3 = parameters to plug into template.
  133.                 lastBtn = item number of last button.
  134.                 staticText = item number of static text field.
  135.                 outline = item number of useritem to outline default button.
  136.                 defaultItem = item number of default button.
  137.                 cancelItem = item number of cancel button, or 0 if none.
  138.                 
  139.     Exit:        function result = item hit.
  140.                 
  141.     This helper function is used by utl_ErrorAlert and utl_SaveChangesAlert.
  142. _____________________________________________________________________*/
  143.  
  144. static short MagicAlert (Str255 tmpl, short dlogID, 
  145.     ModalFilterProcPtr filterProc, Str255 p0, Str255 p1,
  146.     Str255 p2, Str255 p3, short lastBtn, short staticText, short outline,
  147.     short defaultItem, short cancelItem)
  148.  
  149. {
  150.     GrafPtr            savedPort;        /* saved grafport */
  151.     Str255            msg;                /* the error message */
  152.     DialogPtr        dlog;                /* dialog pointer */
  153.     short                itemType;        /* item type */
  154.     Handle            item;                /* handle to item */
  155.     Rect                box;                /* item rectangle */
  156.     short                boxHeight;        /* height of message display rectangle */
  157.     TEHandle            edit;                /* handle to TextEdit record */
  158.     short                height;            /* height of displayed text */
  159.     short                delta;            /* adjustment to height */
  160.     Rect                contrlRect;        /* OK button rectangle */
  161.     Rect                dlogRect;        /* dialog portrect */
  162.     short                itemHit;            /* item hit */
  163.     short                i;                    /* loop index */
  164.         
  165.     GetPort(&savedPort);
  166.         
  167.     /* Create the dialog. */
  168.     
  169.     dlog = GetNewDialog(dlogID, nil, (WindowPtr)-1);
  170.     SetPort(dlog);
  171.     
  172.     /* Plug parameters into the message. */
  173.     
  174.     utl_PlugParams(tmpl, msg, p0, p1, p2, p3);
  175.         
  176.     /* Get TextEdit to figure out how tall the text will be when displayed. */
  177.         
  178.     GetDItem(dlog, staticText, &itemType, &item, &box);
  179.     edit = TENew(&box, &box);
  180.     TESetText(msg+1, *msg, edit);
  181.     TECalText(edit);
  182.     height = (**edit).nLines * (**edit).lineHeight;
  183.     TEDispose(edit);
  184.     
  185.     /* Adjust the height of the dialog, the height of the static text item,
  186.         and the position of the buttons. */
  187.         
  188.     boxHeight = box.bottom - box.top;
  189.     delta = height - boxHeight;
  190.     SizeWindow(dlog, dlog->portRect.right, dlog->portRect.bottom + delta, false);
  191.     box.bottom += delta;
  192.     SetDItem(dlog, staticText, itemType, item, &box);
  193.     for (i = 1; i <= lastBtn; i++) {
  194.         GetDItem(dlog, i, &itemType, &item, &box);
  195.         contrlRect = (**((ControlHandle)item)).contrlRect;
  196.         MoveControl((ControlHandle)item, contrlRect.left, contrlRect.top + delta);
  197.         OffsetRect(&box, 0, delta);
  198.         SetDItem(dlog, i, itemType, item, &box);
  199.     }
  200.     
  201.     /* Center the dialog on the main screen. */
  202.     
  203.     dlogRect = dlog->portRect;
  204.     utl_CenterDlogRect(&dlogRect, true);
  205.     MoveWindow(dlog, dlogRect.left, dlogRect.top, false);
  206.     
  207.     /* Set the user proc to utl_OutlineDefaultButton. */
  208.     
  209.     GetDItem(dlog, outline, &itemType, &item, &box);
  210.     SetDItem(dlog, outline, itemType, (Handle)utl_OutlineDefaultButton, &box);
  211.     
  212.     /* Show the dialog and wait for the user to dismiss it. Use the
  213.         metafilter proc to treat Return and Enter the same as a click on
  214.         the OK button. */
  215.         
  216.     ParamText(msg, nil, nil, nil);
  217.     ShowWindow(dlog);
  218.     Filter = filterProc;
  219.     DefaultItem = defaultItem;
  220.     CancelItem = cancelItem;
  221.     ModalDialog(MetaFilter, &itemHit);
  222.     DisposDialog(dlog);
  223.     SetPort(savedPort);
  224.     return itemHit;
  225. }
  226.  
  227. /*______________________________________________________________________
  228.  
  229.     utl_AppendDITL - Append DITL to End of Dialog.
  230.     
  231.     Entry:    theDialog = pointer to dialog.
  232.                 theDITLID = rsrc id of DITL.
  233.                     
  234.     Exit:        function result = item number of first appended item.
  235.     
  236.     The dialog window is expanded to accomodate the new items, and the
  237.     new items are offset to appear at the bottom of the dialog.
  238.     
  239.     This routine is particularly useful for appending items to the
  240.     standard Page Setup and Print Job dialogs.  (See TN 95).  It was
  241.     written by Lew Rollins of Apple's Human-Systems Interface Group,
  242.     in MPW Pascal.  I translated it to MPW C.
  243.     
  244.     The only significant difference between this routine and Rollin's
  245.     version is that this version does not release the DITL resource.
  246. _____________________________________________________________________*/
  247.  
  248. short utl_AppendDITL (DialogPtr theDialog, short theDITLID)
  249.  
  250. {
  251.     typedef struct DITLItem {
  252.         Handle            itmHndl;                /* handle or proc ptr */
  253.         Rect                itmRect;                /* display rect */
  254.         char                itmType;                /* item type */
  255.         unsigned char    itmData;                /* item data length byte */
  256.     } DITLItem;
  257.     
  258.     typedef struct itemList {
  259.         short                dlgMaxIndex;        /* num items - 1 */
  260.         DITLItem            DITLItems[1];        /* array of DITL items */
  261.     } itemList;
  262.     
  263.     short                offset;            /* item offset */
  264.     Rect                maxRect;            /* max dialog rect size so far */
  265.     Handle            hDITL;            /* handle to DITL */
  266.     DITLItem            *pItem;            /* pointer to item being appended */
  267.     itemList            **hItems;        /* handle to DLOG's item list */
  268.     short                sizeDITL;        /* size of DLOG's item list */
  269.     short                firstItem;        /* item num of first appended item */
  270.     short                newItems;        /* number of new items */
  271.     short                dataSize;        /* size of data for current item */
  272.     short                i;                    /* loop index */
  273.     
  274.     /* Initialize. */
  275.     
  276.     maxRect = theDialog->portRect;
  277.     offset = maxRect.bottom;
  278.     maxRect.bottom -= 5;
  279.     maxRect.right -= 5;
  280.     hItems = (itemList**)(((DialogPeek)theDialog)->items);
  281.     sizeDITL = GetHandleSize((Handle)hItems);
  282.     firstItem = (**hItems).dlgMaxIndex + 2;
  283.     hDITL = GetResource('DITL', theDITLID);
  284.     HLock(hDITL);
  285.     newItems = **(short**)hDITL + 1;
  286.     PtrAndHand(*hDITL+2, (Handle)hItems,
  287.         GetHandleSize(hDITL)-2);
  288.     (**hItems).dlgMaxIndex += newItems;
  289.     HUnlock(hDITL);
  290.     HLock((Handle)hItems);
  291.     pItem = (DITLItem*)((char*)(*hItems) + sizeDITL);
  292.     
  293.     /* Main loop.  Add each item to dialog item list. */
  294.     
  295.     for (i = 1; i <= newItems; i++) {
  296.         OffsetRect(&pItem->itmRect, 0, offset);
  297.         UnionRect(&pItem->itmRect, &maxRect, &maxRect);
  298.         switch (pItem->itmType & 0x7f) {
  299.             case ctrlItem+btnCtrl:
  300.             case ctrlItem+chkCtrl:
  301.             case ctrlItem+radCtrl:
  302.                 pItem->itmHndl = (Handle)NewControl(theDialog, 
  303.                     &pItem->itmRect, &pItem->itmData, true, 0, 0, 1, 
  304.                     pItem->itmType & 0x03, 0);
  305.                 break;
  306.             case ctrlItem+resCtrl:
  307.                 pItem->itmHndl = (Handle)GetNewControl(
  308.                     *(short*)(&pItem->itmData+1),
  309.                     theDialog);
  310.                 (**((ControlHandle)(pItem->itmHndl))).contrlRect = 
  311.                     pItem->itmRect;
  312.                 break;
  313.             case statText:
  314.             case editText:
  315.                 PtrToHand(&pItem->itmData+1, &pItem->itmHndl, pItem->itmData);
  316.                 break;
  317.             case iconItem:
  318.                 pItem->itmHndl = GetIcon(*(short*)(&pItem->itmData+1));
  319.                 break;
  320.             default:
  321.                 pItem->itmHndl = nil;
  322.         }
  323.         dataSize = (pItem->itmData + 1) & 0xfffe;
  324.         pItem = (DITLItem*)((char*)pItem + dataSize + sizeof(DITLItem));
  325.     }
  326.     
  327.     /* Finish up. */
  328.     
  329.     HUnlock((Handle)hItems);
  330.     maxRect.bottom += 5;
  331.     maxRect.right += 5;
  332.     SizeWindow(theDialog, maxRect.right, maxRect.bottom, true);
  333.     return firstItem;
  334. }
  335.  
  336. /*______________________________________________________________________
  337.  
  338.     utl_BuildDialogIBeamRgn - Build Dialog IBeam Region.
  339.     
  340.     Entry:    theDialog = pointer to dialog record.
  341.     
  342.     Exit:        function result = handle to ibeam region.
  343. _____________________________________________________________________*/
  344.  
  345. RgnHandle utl_BuildDialogIBeamRgn (DialogPtr theDialog)
  346.  
  347. {
  348.     short            numItems;            /* number of items */
  349.     RgnHandle    ibRgn;                /* ibeam region */
  350.     RgnHandle    rgn;                    /* scratch region */
  351.     short            itemType;            /* item type */
  352.     Handle        item;                    /* handle to item */
  353.     Rect            box;                    /* item rectangle */
  354.     short            i;                        /* loop index */
  355.     
  356.     ibRgn = NewRgn();
  357.     rgn = NewRgn();
  358.     numItems = **(short**)(((DialogPeek)theDialog)->items) + 1;
  359.     for (i = 1; i <= numItems; i++) {
  360.         GetDItem(theDialog, i, &itemType, &item, &box);
  361.         if ((itemType & 0x7f) == editText) {
  362.             RectRgn(rgn, &box);
  363.             UnionRgn(ibRgn, rgn, ibRgn);
  364.         }
  365.     }
  366.     DisposeRgn(rgn);
  367.     return ibRgn;
  368. }
  369.  
  370. /*______________________________________________________________________
  371.  
  372.     utl_CenterDlogRect - Center a dialog rectangle.
  373.     
  374.     Entry:    rect = rectangle.
  375.                 centerMain = true to center on main (menu bar) screen.
  376.                 centerMain = false to center on the screen containing
  377.                     the maximum intersection with the frontmost window.
  378.     
  379.     Exit:        rect = rectangle offset so that it is centered on
  380.                     the specified screen, with twice as much space below
  381.                     the rect as above.
  382.                     
  383.     See HIN 6.
  384. _____________________________________________________________________*/
  385.  
  386. void utl_CenterDlogRect (Rect *rect, Boolean centerMain)
  387.  
  388. {
  389.     Rect        screenRect;            /* screen rectangle */
  390.     short        mBHeight;            /* menu bar height */
  391.     GDHandle    gd;                    /* gdevice */
  392.     Rect        windRect;            /* window rectangle */
  393.     Boolean    hasMB;                /* true if screen contains menu bar */
  394.  
  395.     mBHeight = utl_GetMBarHeight();
  396.     if (centerMain) {
  397.         screenRect = qd.screenBits.bounds;
  398.     } else {
  399.         utl_GetWindGD(FrontWindow(), &gd, &screenRect, &windRect, &hasMB);
  400.         if (!hasMB) mBHeight = 0;
  401.     }
  402.     OffsetRect(rect,
  403.         (screenRect.right + screenRect.left - rect->right - rect->left) >> 1,
  404.         (screenRect.bottom + ((screenRect.top + mBHeight - rect->top)<<1) - 
  405.             rect->bottom + 7) / 3);
  406. }
  407.  
  408. /*______________________________________________________________________
  409.  
  410.     utl_CenterRect - Center a rectangle on the main screen.
  411.     
  412.     Entry:    rect = rectangle.
  413.     
  414.     Exit:        rect = rectangle offset so that it is centered on
  415.                     the main screen.
  416. _____________________________________________________________________*/
  417.  
  418. void utl_CenterRect (Rect *rect)
  419.  
  420. {
  421.     Rect        screenRect;            /* main screen rectangle */
  422.     short        mBHeight;            /* menu bar height */
  423.  
  424.     mBHeight = utl_GetMBarHeight();
  425.     screenRect = qd.screenBits.bounds;
  426.     OffsetRect(rect,
  427.         (screenRect.right + screenRect.left - rect->right - rect->left) >> 1,
  428.         (screenRect.bottom - screenRect.top + mBHeight - 
  429.             rect->bottom - rect->top) >> 1);
  430. }
  431.  
  432. /*______________________________________________________________________
  433.  
  434.     utl_CheckAERequiredParams - Check Required Apple Event Parameters.
  435.     
  436.     Entry:    event = pointer to Apple event.
  437.     
  438.     Exit:        function result = noErr if all required parameters feteched.
  439.                 function result = errAEEventNotHandled if some event 
  440.                     contains unfetched required parameters.
  441.                 function result = error code if some other error.
  442.     
  443.     See IM VI 6-47.
  444. _____________________________________________________________________*/
  445.  
  446. OSErr utl_CheckAERequiredParams (AppleEvent *event)
  447.  
  448. {
  449.     DescType            theType;
  450.     long                actualSize;
  451.     OSErr                rCode;
  452.     
  453.     rCode = AEGetAttributePtr(event, keyMissedKeywordAttr, typeWildCard,
  454.         &theType, nil, 0, &actualSize);
  455.     if (rCode == errAEDescNotFound) {
  456.         return noErr;
  457.     } else if (rCode == noErr) {
  458.         return errAEEventNotHandled;
  459.     } else {
  460.         return rCode;
  461.     }
  462. }
  463.  
  464. /*______________________________________________________________________
  465.  
  466.     utl_CheckPack - Check to see if a package exists.
  467.     
  468.     Entry:    packNum = package number.
  469.                 preload = true to preload package.
  470.                     
  471.     Exit:        function result = true if package exists.
  472. _____________________________________________________________________*/
  473.  
  474. Boolean utl_CheckPack (short packNum, Boolean preload)
  475.  
  476. {
  477.     short            trapNum;            /* trap number */
  478.     Handle        h;                    /* handle to PACK resource */
  479.     
  480.     /* Check to make sure the trap exists, by comparing its trap address to
  481.         the trap address of the unimplemented trap. */
  482.     
  483.     trapNum = packNum + 0x1e7;
  484.     if (NGetTrapAddress(trapNum & 0x3ff, ToolTrap) == 
  485.         NGetTrapAddress(_Unimplemented & 0x3ff, ToolTrap)) return false;
  486.         
  487.     /* Check to make sure the package exists on the System file or in 
  488.         ROM.  If it's not in ROM make it nonpurgeable, if requested. */
  489.     
  490.     if (preload) {
  491.         if (utl_Rom64()) {
  492.             h = GetResource('PACK', packNum);
  493.             if (!h) return false;
  494.             HNoPurge(h);
  495.         } else {
  496.             *(unsigned short*)RomMapInsert = 0xFF00;
  497.             h = GetResource('PACK', packNum);
  498.             if (!h) return false;
  499.             if ((*(unsigned long*)h & 0x00FFFFFF) < 
  500.                 *(unsigned long*)ROMBase) {
  501.                 h = GetResource('PACK', packNum);
  502.                 HNoPurge(h);
  503.             }
  504.         }
  505.         return true;
  506.     } else {
  507.         SetResLoad(false);
  508.         if (!utl_Rom64()) *(unsigned short*)RomMapInsert = 0xFF00;
  509.         h = GetResource('PACK', packNum);
  510.         SetResLoad(true);
  511.         if (h) return true; else return false;
  512.     }
  513. }
  514.  
  515. /*______________________________________________________________________
  516.  
  517.     utl_CheckSpecialDialogKey - Check for Special Dialog Key.
  518.     
  519.     Entry:    theDialog = pointer to dialog record.
  520.                 theKey = ascii code of the key pressed.
  521.                 modifiers = modifiers from event record.
  522.                 defaultItem = default button item number, or 0 if none.
  523.                 cancelItem = cancel button item number, or 0 if none.
  524.                 
  525.     Exit:        function result = item number of special button, or 0 if
  526.                     none.
  527.                     
  528.     Return and enter are treated the same as clicks on the default button.
  529.     Escape and command-period are treated the same as clicks on the cancel
  530.     button.
  531.     Buttons are flashed.
  532. _____________________________________________________________________*/
  533.  
  534. short utl_CheckSpecialDialogKey (DialogPtr theDialog, char theKey,
  535.     short modifiers, short defaultItem, short cancelItem)
  536.     
  537. {
  538.     if (defaultItem && (theKey == returnKey || theKey == enterKey)) {
  539.         utl_FlashDialogButton(theDialog, defaultItem);
  540.         return defaultItem;
  541.     } else if (cancelItem && 
  542.         (theKey == escapeKey || ((modifiers & cmdKey) && theKey == '.'))) {
  543.         utl_FlashDialogButton(theDialog, cancelItem);
  544.         return cancelItem;
  545.     } else {
  546.         return 0;
  547.     }
  548. }
  549.  
  550. /*______________________________________________________________________
  551.  
  552.     utl_CopyPString - Copy Pascal String.
  553.     
  554.     Entry:    dest = destination string.
  555.                 source = source string.
  556. _____________________________________________________________________*/
  557.  
  558. void utl_CopyPString (Str255 dest, Str255 source)
  559.  
  560. {
  561.     memcpy(dest, source, *source+1);
  562. }
  563.  
  564. /*______________________________________________________________________
  565.  
  566.     utl_CouldDrag - Determine if a window could be dragged to a location.
  567.     
  568.     Entry:    windRect = window rectangle, in global coords.
  569.                 offset = pixel offset used in DragRect calls.
  570.     
  571.     Exit:        function result = true if the window could have been
  572.                     dragged to the specified position.
  573.                     
  574.     This routine is used when restoring windows to saved positions.  According
  575.     to HIN 6, we must check to see if the window "could have been dragged to
  576.     the saved position."
  577.     
  578.     The "offset" parameter is usually 4.  When initializing the boundary rectangle
  579.     for DragWindow calls, normally the boundary rectangle of the desktop gray
  580.     region is inset by 4 pixels.  If some value other than 4 is used, it should
  581.     be passed to CouldDrag as the "offset" parameter.
  582.     
  583.     The algorithm used is the following:  The routine computes the four squares
  584.     at the corners of the title bar.  "true" is returned if and only if at least one 
  585.     of these four squares is completely contained within the desktop gray region.
  586.     
  587.     Three pixels are added to the offset to err on the side of requiring a larger
  588.     portion of the drag bar to be visible.  
  589. _____________________________________________________________________*/
  590.  
  591. Boolean utl_CouldDrag (Rect *windRect, short offset)
  592.  
  593. {
  594.     RgnHandle            rgn;            /* scratch region handle */
  595.     Boolean                could;        /* function result */
  596.     short                    corner;        /* which corner */
  597.     Rect                    r;                /* corner rectangle */
  598.  
  599.     rgn = NewRgn();
  600.     could = false;
  601.     offset += 3;
  602.     for (corner = 1; corner <= 4; corner++) {
  603.         switch (corner) {
  604.             case 1:
  605.                 r.top = windRect->top - titleBarHeight;
  606.                 r.left = windRect->left;
  607.                 break;
  608.             case 2:
  609.                 r.top = windRect->top - offset;
  610.                 r.left = windRect->left;
  611.                 break;
  612.             case 3:
  613.                 r.top = windRect->top - titleBarHeight;
  614.                 r.left = windRect->right - offset;
  615.                 break;
  616.             case 4:
  617.                 r.top = windRect->top - offset;
  618.                 r.left = windRect->right - offset;
  619.                 break;
  620.         }
  621.         r.bottom = r.top + offset;
  622.         r.right = r.left + offset;
  623.         RectRgn(rgn, &r);
  624.         DiffRgn(rgn, *(RgnHandle*)GrayRgn, rgn);
  625.         if (EmptyRgn(rgn)) {
  626.             could = true;
  627.             break;
  628.         }
  629.     }
  630.     DisposeRgn(rgn);
  631.     return could;
  632. }
  633.  
  634. /*______________________________________________________________________
  635.  
  636.     utl_CountProcesses - Count Processes.
  637.     
  638.     Exit:        function result = error code.
  639.                 count = number of active processes.
  640.                 
  641.     System 7.0 only.
  642. _____________________________________________________________________*/
  643.  
  644. OSErr utl_CountProcesses (short *count)
  645.     
  646. {
  647.     OSErr                        rCode;                /* result code */
  648.     ProcessSerialNumber    psn;                    /* process serial number */
  649.  
  650.     *count = 0;
  651.     psn.highLongOfPSN = 0;
  652.     psn.lowLongOfPSN = kNoProcess;
  653.     while (!(rCode = GetNextProcess(&psn))) (*count)++;
  654.     if (rCode == procNotFound) rCode = noErr;
  655.     return rCode;
  656. }
  657.  
  658. /*______________________________________________________________________
  659.  
  660.     utl_DILoad - Load Disk Initialization Package.
  661.     
  662.     Exit:        Disk initialization package loaded.
  663.                 
  664.     This routine is identical to the DILoad routine (see IM II-396),
  665.     except that it closes any resource files opened by the routine.  This is
  666.     necessary to undo a bug in the DaynaFile software.  DaynaFile patches
  667.     DILoad.  The patch opens a resource file without closing it.  The
  668.     effect on Disinfectant if we don't do anything about this is that 
  669.     the DaynaFile icon is displayed in Disinfectant's main window instead of
  670.     Disinfectant's icon.  
  671. _____________________________________________________________________*/
  672.  
  673. void utl_DILoad (void)
  674.  
  675. {
  676.     short            curResFile;            /* ref num of current resource file
  677.                                                 before calling DILoad */
  678.     short            topResFile;            /* ref num of top resource file
  679.                                                 after calling DILoad */
  680.     
  681.     curResFile = CurResFile();
  682.     DILoad();
  683.     while ((topResFile = CurResFile()) != curResFile) CloseResFile(topResFile);
  684. }
  685.  
  686. /*______________________________________________________________________
  687.  
  688.     utl_DoDiskInsert - Handle a disk inserted event.
  689.     
  690.     Entry:    message = message field from disk insertion event record
  691.                     = 16/MountVol return code, 16/drive number.
  692.     
  693.     Exit:        vRefNum = vol ref num of inserted volume.
  694.                 function result = error code.
  695.     
  696.     If MountVol returned an error code, the disk initialization package
  697.     is called to initialize the disk.
  698. _____________________________________________________________________*/
  699.  
  700. OSErr utl_DoDiskInsert (long message, short *vRefNum)
  701.  
  702. {
  703.     OSErr                rCode;                /* result code */
  704.     short                driveNum;            /* drive number */
  705.     HParamBlockRec    pBlock;                /* vol info param block */
  706.     Handle            dlgHandle;            /* handle to disk init dialog */
  707.     Rect                dlgRect;                /* disk init dialog rectangle */
  708.     Point                where;                /* location of disk init dialog */
  709.     short                curVol;                /* index in VCB queue */
  710.     
  711.     /* Get result code and drive number from event message. */
  712.     
  713.     rCode = (message >> 16) & 0xffff;
  714.     driveNum = message & 0xffff;
  715.     
  716.     /* If the result code indicates an error, call DIBadMount to initialize
  717.         the disk. */
  718.         
  719.     if (rCode) {
  720.         
  721.         /* Center the disk initialization package dialog. */
  722.         
  723.         DILoad();
  724.         dlgHandle = GetResource('DLOG', -6047);
  725.         dlgRect = **(Rect**)dlgHandle;
  726.         utl_CenterDlogRect(&dlgRect, false);
  727.         SetPt(&where, dlgRect.left, dlgRect.top);
  728.         
  729.         /* Call DIBadMount. */
  730.         
  731.         if (rCode = DIBadMount(where, message)) return rCode;
  732.         
  733.     }
  734.     
  735.     /* Search mounted volumes to find inserted one. */
  736.     
  737.     pBlock.volumeParam.ioNamePtr = nil;
  738.     curVol = 0;
  739.     while (true) {
  740.         pBlock.volumeParam.ioVolIndex = ++curVol;
  741.         pBlock.volumeParam.ioVRefNum = 0;
  742.         if (rCode = PBHGetVInfo(&pBlock, false)) return rCode;
  743.         if (pBlock.volumeParam.ioVDrvInfo == driveNum) break;
  744.     }
  745.     *vRefNum = pBlock.volumeParam.ioVRefNum;
  746.     return noErr;
  747. }    
  748.  
  749. /*______________________________________________________________________
  750.  
  751.     utl_DrawGrowIcon - Draw Grow Icon.
  752.     
  753.     Entry:            theWindow = pointer to window.
  754.     
  755.     This routine is identical to the Window Manager routine 
  756.     DrawGrowIcon, except that it does not draw the lines enclosing the
  757.     scroll bars.
  758. _____________________________________________________________________*/
  759.  
  760. void utl_DrawGrowIcon (WindowPtr theWindow) 
  761.  
  762. {
  763.     RgnHandle            clipRgn;            /* saved clip region */
  764.     Rect                    clipRect;        /* clip rectangle */
  765.     
  766.     clipRgn = NewRgn();
  767.     GetClip(clipRgn);
  768.     clipRect = theWindow->portRect;
  769.     clipRect.left = clipRect.right - 15;
  770.     clipRect.top = clipRect.bottom - 15;
  771.     ClipRect(&clipRect);
  772.     DrawGrowIcon(theWindow);
  773.     SetClip(clipRgn);
  774.     DisposeRgn(clipRgn);
  775. }
  776.  
  777. /*______________________________________________________________________
  778.  
  779.     utl_Ejectable - Test for ejectable volume.
  780.     
  781.     Entry:    vRefNum = volume reference number.
  782.     
  783.     Exit:        function result = true if volume is on an ejectable drive.
  784. _____________________________________________________________________*/
  785.  
  786. Boolean utl_Ejectable (short vRefNum)
  787.     
  788. {
  789.     HParamBlockRec    pBlock;                /* vol info param block */
  790.     short                driveNum;            /* driver number of cur vol */
  791.     DrvQEl            *curDrive;            /* ptr to current drive queue element */
  792.     OSErr                rCode;                /* result code */
  793.     unsigned char    flagByte;            /* drive queue element flag byte */
  794.     
  795.     /* Get driveNum = drive number of drive containing volume. */
  796.     
  797.     pBlock.volumeParam.ioNamePtr = nil;
  798.     pBlock.volumeParam.ioVolIndex = 0;
  799.     pBlock.volumeParam.ioVRefNum = vRefNum;;
  800.     if (rCode = PBHGetVInfo(&pBlock, false)) return false;
  801.     driveNum = pBlock.volumeParam.ioVDrvInfo;
  802.     
  803.     /*    Walk the drive queue until we find driveNum.  The second byte in
  804.         the four flag bytes preceding the drive queue element is 8 or $48 
  805.         if the drive is nonejectable. */
  806.     
  807.     curDrive = (DrvQEl*)(GetDrvQHdr())->qHead;
  808.     while (true) {
  809.         if (curDrive->dQDrive == driveNum) {
  810.             flagByte = *((Ptr)curDrive - 3);
  811.             return (flagByte != 8 && flagByte != 0x48);
  812.         }
  813.         curDrive = (DrvQEl*)curDrive->qLink;
  814.         if (!curDrive) return false;
  815.     }
  816. }
  817.  
  818. /*______________________________________________________________________
  819.  
  820.     utl_ErrorAlert - Present an Error Alert.
  821.     
  822.     Entry:    tmpl = error message template.
  823.                 dlogID = resource id of error message dialog.
  824.                 filterProc = pointer to filter proc.
  825.                 p0,p1,p2,p3 = parameters to plug into template.
  826.                 
  827.     The error message dialog must have:
  828.     item 1 = OK button.
  829.     item 2 = stop icon.
  830.     item 3 = static text field with content "^0".
  831.     item 4 = user item used to outline the OK button.
  832.     
  833.     This function adjusts the height of the alert and the static text
  834.     field so that they are just high enough to contain the message.
  835. _____________________________________________________________________*/
  836.  
  837. void utl_ErrorAlert (Str255 tmpl, short dlogID,
  838.     ModalFilterProcPtr filterProc, Str255 p0, Str255 p1,
  839.     Str255 p2, Str255 p3)
  840.  
  841. {
  842.     SysBeep(0);
  843.     MagicAlert(tmpl, dlogID, filterProc, p0, p1, p2, p3, 1, 3, 4, 1, 0);
  844. }
  845.  
  846. /*______________________________________________________________________
  847.  
  848.     utl_ErrorAlertRez - Present an Error Alert.
  849.     
  850.     Entry:    rezID = resource id of STR# resource containing message
  851.                     template.
  852.                 index = index in STR# resource of message template.
  853.                 dlogID = resource id of error message dialog.
  854.                 filterProc = pointer to filter proc.
  855.                 p0, p1, p2, p3 = parameters to plug into template.
  856. _____________________________________________________________________*/
  857.  
  858. void utl_ErrorAlertRez (short rezID, short index, short dlogID,
  859.     ModalFilterProcPtr filterProc, 
  860.     Str255 p0, Str255 p1, Str255 p2, Str255 p3)
  861.     
  862. {
  863.     Str255            tmpl;            /* message template */
  864.     
  865.     GetIndString(tmpl, rezID, index);
  866.     utl_ErrorAlert(tmpl, dlogID, filterProc, p0, p1, p2, p3);
  867. }
  868.  
  869. /*______________________________________________________________________
  870.  
  871.     utl_FixStdFile - Fix Standard File Pacakge.
  872.     
  873.     This routine should be called before calling the Standard File 
  874.     package if there's any chance that SFSaveDisk might specify
  875.     a volume that has been unmounted.  Standard File gets confused if this
  876.     happens and presents an alert telling the user that a "system error"
  877.     has occurred.
  878.     
  879.     This routine checks to make sure that SFSaveDisk specifies a volume 
  880.     that is still mounted.  If not, it sets it to the first mounted 
  881.     volume, and it sets CurDirStore to the root directory on that volume.
  882. _____________________________________________________________________*/
  883.                     
  884. void utl_FixStdFile (void)
  885.  
  886. {
  887.     ParamBlockRec    vBlock;            /* vol info param block */
  888.                                                 
  889.     vBlock.volumeParam.ioNamePtr = nil;
  890.     vBlock.volumeParam.ioVRefNum = -*(short*)SFSaveDisk;
  891.     vBlock.volumeParam.ioVolIndex = 0;
  892.     if (PBGetVInfo(&vBlock, false)) {
  893.         vBlock.volumeParam.ioVolIndex = 1;
  894.         (void) PBGetVInfo(&vBlock, false);
  895.         *(short*)SFSaveDisk = -vBlock.volumeParam.ioVRefNum;
  896.         if (*(short*)FSFCBLen > 0) *(long*)CurDirStore = fsRtDirID;
  897.     }
  898. }
  899.  
  900. /*______________________________________________________________________
  901.  
  902.     utl_FlashButton - Flash Button.
  903.     
  904.     Entry:    theButton = handle to button control..
  905.                 
  906.     The push button is inverted for 8 ticks.  See HIN #10.
  907. _____________________________________________________________________*/
  908.  
  909. void utl_FlashButton (ControlHandle theButton)
  910.  
  911. {
  912.     Rect            box;                    /* control rectangle */
  913.     short            roundFactor;        /* rounded corner factor for InvertRoundRect */
  914.     long            tickEnd;                /* tick count to end flash */
  915.     
  916.     box = (**theButton).contrlRect;
  917.     roundFactor = (box.bottom - box.top)>>1;
  918.     InvertRoundRect(&box, roundFactor, roundFactor);
  919.     tickEnd = TickCount() + 8;
  920.     while (TickCount() < tickEnd);
  921.     InvertRoundRect(&box, roundFactor, roundFactor);
  922. }
  923.  
  924. /*______________________________________________________________________
  925.  
  926.     utl_FlashDialogButton - Flash Dialog Button.
  927.     
  928.     Entry:    theDialog = pointer to dialog.
  929.                 itemNo = item number of button to flash.
  930.                 
  931.     The push button is inverted for 8 ticks.  See HIN #10.
  932. _____________________________________________________________________*/
  933.  
  934. void utl_FlashDialogButton (DialogPtr theDialog, short itemNo)
  935.  
  936. {
  937.     short            itemType;            /* item type */
  938.     Handle        item;                    /* item handle */
  939.     Rect            box;                    /* item rectangle */
  940.     
  941.     GetDItem(theDialog, itemNo, &itemType, &item, &box);
  942.     SetPort(theDialog);
  943.     utl_FlashButton((ControlHandle)item);
  944. }
  945.  
  946. /*______________________________________________________________________
  947.  
  948.     utl_FrameItem
  949.     
  950.     Entry:    theWindow = pointer to dialog window.
  951.                 itemNo = dialog item number.
  952.     
  953.     Exit:        dialog item rectangle framed.
  954.                 
  955.     This function is for use as a Dialog Manager user item procedure.
  956.     It is particularly useful for drawing rules (straight lines).  Simply
  957.     define the user item rectangle with bottom=top+1 or right=left+1.
  958. _____________________________________________________________________*/
  959.  
  960. pascal void utl_FrameItem (WindowPtr theWindow, short itemNo)
  961.  
  962. {
  963.     short            itemType;            /* item type */
  964.     Handle        item;                    /* item handle */
  965.     Rect            box;                    /* item rectangle */
  966.  
  967.     GetDItem(theWindow, itemNo, &itemType, &item, &box);
  968.     FrameRect(&box);
  969. }
  970.  
  971. /*______________________________________________________________________
  972.  
  973.     utl_GestaltFlag - Get Gestalt Flag.
  974.     
  975.     Entry:    selector = Gestalt selector.
  976.                 bitNum = flag bit number.
  977.     
  978.     Exit:        function result = true if flag set.
  979. _____________________________________________________________________*/
  980.  
  981. Boolean utl_GestaltFlag (OSType selector, short bitNum)
  982.  
  983. {
  984.     long            result;            /* result from call to Gestalt */
  985.     
  986.     return !Gestalt(selector, &result) &&
  987.         ((result >> bitNum) & 1);
  988. }
  989.  
  990. /*______________________________________________________________________
  991.  
  992.     utl_GetApplVol - Get the volume reference number of the application volume.
  993.     
  994.     Exit:        function result = volume reference number of the volume 
  995.                     containing the current application.
  996. _____________________________________________________________________*/
  997.  
  998. short utl_GetApplVol (void)
  999.  
  1000. {
  1001.     short            vRefNum;                /* vol ref num */
  1002.  
  1003.     GetVRefNum(*(short*)(CurMap), &vRefNum);
  1004.     return vRefNum;
  1005. }
  1006.  
  1007. /*______________________________________________________________________
  1008.  
  1009.     utl_GetBlessedWDRefNum - Get the working directory reference number of
  1010.         the Blessed Folder.
  1011.     
  1012.     Exit:        function result = wdRefNum of blessed folder
  1013. _____________________________________________________________________*/
  1014.  
  1015. short utl_GetBlessedWDRefNum (void)
  1016.  
  1017. {
  1018.     if (!GotSysEnviron) GetSysEnvirons();
  1019.     return TheWorld.sysVRefNum;
  1020. }
  1021.  
  1022. /*______________________________________________________________________
  1023.  
  1024.     utl_GetDialogControlValue - Get Dialog Control Value.
  1025.     
  1026.     Entry:    theDialog = pointer to dialog record.
  1027.                 itemNo = item number of control.
  1028.     
  1029.     Exit:        function result = value of control.
  1030. _____________________________________________________________________*/
  1031.  
  1032. short utl_GetDialogControlValue (DialogPtr theDialog, short itemNo)
  1033.  
  1034. {
  1035.     short        itemType;            /* item type */
  1036.     Handle    item;                    /* handle to item */
  1037.     Rect        box;                    /* item rectangle */
  1038.  
  1039.     GetDItem(theDialog, itemNo, &itemType, &item, &box);
  1040.     return GetCtlValue((ControlHandle)item);
  1041. }
  1042.  
  1043. /*______________________________________________________________________
  1044.  
  1045.     utl_GetDialogEditFieldNum - Get Dialog Edit Field Number.
  1046.     
  1047.     Entry:    theDialog = pointer to dialog record.
  1048.     
  1049.     Exit:        function result = field number of current TextEdit field.
  1050. _____________________________________________________________________*/
  1051.  
  1052. short utl_GetDialogEditFieldNum (DialogPtr theDialog)
  1053.  
  1054. {
  1055.     return ((DialogPeek)theDialog)->editField + 1;
  1056. }
  1057.  
  1058. /*______________________________________________________________________
  1059.  
  1060.     utl_GetDialogNumericValue - Get Dialog Numeric Value.
  1061.     
  1062.     Entry:    theDialog = pointer to dialog record.
  1063.                 itemNo = item number of control.
  1064.     
  1065.     Exit:        function result = item value.
  1066. _____________________________________________________________________*/
  1067.  
  1068. long utl_GetDialogNumericValue (DialogPtr theDialog, short itemNo)
  1069.  
  1070. {
  1071.     short        itemType;            /* item type */
  1072.     Handle    item;                    /* handle to item */
  1073.     Rect        box;                    /* item rectangle */
  1074.     Str255    theText;                /* item text */
  1075.     long        theNum;                /* the item value */
  1076.  
  1077.     GetDItem(theDialog, itemNo, &itemType, &item, &box);
  1078.     GetIText(item, theText);
  1079.     StringToNum(theText, &theNum);
  1080.     return theNum;
  1081. }
  1082.  
  1083. /*______________________________________________________________________
  1084.  
  1085.     utl_GetDialogPopupValue - Get Dialog Popup Menu Value.
  1086.     
  1087.     Entry:    theDialog = pointer to dialog record.
  1088.                 itemNo = item number of control.
  1089.     
  1090.     Exit:        val = value of currently selected menu item.
  1091.     
  1092.     (System 7 only)
  1093. _____________________________________________________________________*/
  1094.  
  1095. void utl_GetDialogPopupValue (DialogPtr theDialog, short itemNo, 
  1096.     Str255 val)
  1097.     
  1098. {
  1099.     short                itemType;        /* item type */
  1100.     ControlHandle    theControl;        /* handle to control */
  1101.     Rect                box;                /* item rectangle */
  1102.     MenuHandle        theMenu;            /* handle to menu */
  1103.     
  1104.     GetDItem(theDialog, itemNo, &itemType, (Handle*)&theControl, &box);
  1105.     theMenu = (**((popupPrivateData**)(**theControl).contrlData)).mHandle;
  1106.     GetItem(theMenu, GetCtlValue(theControl), val);
  1107. }
  1108.  
  1109. /*______________________________________________________________________
  1110.  
  1111.     utl_GetDialogText - Get Dialog Item Text.
  1112.     
  1113.     Entry:    theDialog = pointer to dialog record.
  1114.                 itemNo = item number of statText or editText item.
  1115.     
  1116.     Exit:        theText = the text.
  1117. _____________________________________________________________________*/
  1118.  
  1119. void utl_GetDialogText (DialogPtr theDialog, short itemNo, Str255 theText)
  1120.  
  1121. {
  1122.     short        itemType;            /* item type */
  1123.     Handle    item;                    /* handle to item */
  1124.     Rect        box;                    /* item rectangle */
  1125.  
  1126.     GetDItem(theDialog, itemNo, &itemType, &item, &box);
  1127.     GetIText(item, theText);
  1128. }
  1129.  
  1130. /*______________________________________________________________________
  1131.  
  1132.     utl_GetFontNumber - Get Font Number.
  1133.     
  1134.     Entry:    fontName = font name.
  1135.     
  1136.     Exit:        function result = true if font exists.
  1137.                 fontNum = font number.
  1138.                 
  1139.     Copied from TN 191.
  1140. _____________________________________________________________________*/
  1141.  
  1142. Boolean utl_GetFontNumber (Str255 fontName, short *fontNum)
  1143.  
  1144. {
  1145.     Str255        systemFontName;
  1146.     
  1147.     GetFNum(fontName, fontNum);
  1148.     if (*fontNum) {
  1149.         return true;
  1150.     } else {
  1151.         GetFontName(0, systemFontName);
  1152.         return EqualString(fontName, systemFontName, false, false);
  1153.     }
  1154. }
  1155.  
  1156. /*______________________________________________________________________
  1157.  
  1158.     utl_GetLongSleep - Get Long Sleep Time.
  1159.     
  1160.     Exit:            function result = long sleep time.
  1161.     
  1162.     Returns the largest positive long integer (0x7fffffff) if the 
  1163.     system version is > 0x04ff, else returns 50.  See TN 177.
  1164. _____________________________________________________________________*/
  1165.  
  1166. long utl_GetLongSleep (void)
  1167.  
  1168. {
  1169.     if (!GotSysEnviron) GetSysEnvirons();
  1170.     return (TheWorld.systemVersion > 0x04ff) ? 0x7fffffff : 50;
  1171. }
  1172.  
  1173. /*______________________________________________________________________
  1174.  
  1175.     utl_GetMBarHeight - Get Menu Bar Height
  1176.     
  1177.     Exit:        function result = menu bar height.
  1178.     
  1179.     See TN 117.
  1180. _____________________________________________________________________*/
  1181.  
  1182. short utl_GetMBarHeight (void)
  1183.  
  1184. {
  1185.     static short        mBHeight = 0;
  1186.     
  1187.     if (!mBHeight) {
  1188.         mBHeight = utl_Rom64() ? 20 : *(short*)MBarHeight;
  1189.     }
  1190.     return mBHeight;
  1191. }
  1192.  
  1193. /*______________________________________________________________________
  1194.  
  1195.     utl_GetNewControl - Get New Control.
  1196.     
  1197.     Entry:    controlID = resource id of CNTL resource.
  1198.                 theWindow = pointer to window record.
  1199.                 
  1200.     Exit:        function result = handle to new control record.
  1201.                 
  1202.     This routine is identical to the Control Manager routine GetNewControl,
  1203.     except it does not release or make purgeable the CNTL resource.
  1204. _____________________________________________________________________*/
  1205.  
  1206. ControlHandle utl_GetNewControl (short controlID, 
  1207.     WindowPtr theWindow)
  1208.     
  1209. {
  1210.     Rect            boundsRect;            /* boundary rectangle */
  1211.     short            value;                /* initial control value */
  1212.     Boolean        visible;                /* true if visible */
  1213.     short            max;                    /* max control value */
  1214.     short            min;                    /* min control value */
  1215.     short            procID;                /* window proc id */
  1216.     long            refCon;                /* refCon field for window record */
  1217.     Str255        title;                /* window title */
  1218.     Handle        theRez;                /* handle to CNTL resource */
  1219.     
  1220.     theRez = GetResource('CNTL', controlID);
  1221.     boundsRect = *(Rect*)(*theRez);
  1222.     value = *(short*)(*theRez+8);
  1223.     visible = *(Boolean*)(*theRez+10);
  1224.     max = *(short*)(*theRez+12);
  1225.     min = *(short*)(*theRez+14);
  1226.     procID = *(short*)(*theRez+16);
  1227.     refCon = *(long*)(*theRez+18);
  1228.     utl_CopyPString(title, (unsigned char*)*theRez+22);
  1229.     return NewControl(theWindow, &boundsRect, title, visible, value,
  1230.         min, max, procID, refCon);
  1231. }
  1232.  
  1233. /*______________________________________________________________________
  1234.  
  1235.     utl_GetNewDialog - Get New Dialog.
  1236.     
  1237.     Entry:    dialogID = resource id of DLOG resource.
  1238.                 dStorage = pointer to dialog record.
  1239.                 behind = window to insert in back of.
  1240.                 
  1241.     Exit:        function result = pointer to new dialog record.
  1242.                 
  1243.     This routine is identical to the Dialog Manager routine GetNewDialog,
  1244.     except it does not release or make purgeable the DLOG resource.
  1245. _____________________________________________________________________*/
  1246.  
  1247. DialogPtr utl_GetNewDialog (short dialogID, Ptr dStorage, 
  1248.     WindowPtr behind)
  1249.     
  1250. {
  1251.     Rect            boundsRect;            /* boundary rectangle */
  1252.     short            procID;                /* window proc id */
  1253.     Boolean        visible;                /* true if visible */
  1254.     Boolean        goAwayFlag;            /* true if window has go away box */
  1255.     long            refCon;                /* refCon field for window record */
  1256.     Str255        title;                /* window title */
  1257.     Handle        theRez;                /* handle to DLOG resource */
  1258.     short            itemID;                /* rsrc id of item list */
  1259.     Handle        items;                /* handle to item list */
  1260.     
  1261.     theRez = GetResource('DLOG', dialogID);
  1262.     boundsRect = *(Rect*)(*theRez);
  1263.     procID = *(short*)(*theRez+8);
  1264.     visible = *(Boolean*)(*theRez+10);
  1265.     goAwayFlag = *(Boolean*)(*theRez+12);
  1266.     refCon = *(long*)(*theRez+14);
  1267.     itemID = *(short*)(*theRez+18);
  1268.     utl_CopyPString(title, (unsigned char*)*theRez+20);
  1269.     items = GetResource('DITL', itemID);
  1270.     return NewDialog(dStorage, &boundsRect, title, visible, procID, behind,
  1271.         goAwayFlag, refCon, items);
  1272. }
  1273.  
  1274. /*______________________________________________________________________
  1275.  
  1276.     utl_GetNewWindow - Get New Window.
  1277.     
  1278.     Entry:    windowID = resource id of WIND resource.
  1279.                 wStorage = pointer to window record.
  1280.                 behind = window to insert in back of.
  1281.                 
  1282.     Exit:        function result = pointer to new window record.
  1283.                 
  1284.     This routine is identical to the Window Manager routine GetNewWindow,
  1285.     except it does not release or make purgeable the WIND resource.
  1286. _____________________________________________________________________*/
  1287.  
  1288. WindowPtr utl_GetNewWindow (short windowID, Ptr wStorage, 
  1289.     WindowPtr behind)
  1290.     
  1291. {
  1292.     Rect            boundsRect;            /* boundary rectangle */
  1293.     short            procID;                /* window proc id */
  1294.     Boolean        visible;                /* true if visible */
  1295.     Boolean        goAwayFlag;            /* true if window has go away box */
  1296.     long            refCon;                /* refCon field for window record */
  1297.     Str255        title;                /* window title */
  1298.     Handle        theRez;                /* handle to WIND resource */
  1299.     
  1300.     theRez = GetResource('WIND', windowID);
  1301.     boundsRect = *(Rect*)(*theRez);
  1302.     procID = *(short*)(*theRez+8);
  1303.     visible = *(Boolean*)(*theRez+10);
  1304.     goAwayFlag = *(Boolean*)(*theRez+12);
  1305.     refCon = *(long*)(*theRez+14);
  1306.     utl_CopyPString(title, (unsigned char*)*theRez+18);
  1307.     return NewWindow(wStorage, &boundsRect, title, visible, procID, behind,
  1308.         goAwayFlag, refCon);
  1309. }
  1310.  
  1311. /*______________________________________________________________________
  1312.  
  1313.     utl_GetSysDirID - Get Directory ID of Blessed Folder.
  1314.     
  1315.     Exit:        function result = directory id of blessed folder, or 0 if
  1316.                     MFS volume.
  1317. _____________________________________________________________________*/
  1318.  
  1319. long utl_GetSysDirID (void)
  1320.  
  1321. {
  1322.     short            sysVol;            /* sys vol ref num */
  1323.     FCBPBRec        fcbBlock;        /* file info param block */
  1324.     
  1325.     sysVol = utl_GetSysVol();
  1326.     if (utl_VolIsMFS(sysVol)) {
  1327.         return 0;
  1328.     } else {
  1329.         fcbBlock.ioNamePtr = nil;
  1330.         fcbBlock.ioVRefNum = 0;
  1331.         fcbBlock.ioRefNum = *((short*)SysMap);
  1332.         fcbBlock.ioFCBIndx = 0;
  1333.         (void) PBGetFCBInfo(&fcbBlock, false);
  1334.         return fcbBlock.ioFCBParID;
  1335.     }
  1336. }
  1337.  
  1338. /*______________________________________________________________________
  1339.  
  1340.     utl_GetSysVol - Get the volume reference number of the system volume.
  1341.     
  1342.     Exit:        function result = volume reference number of the volume 
  1343.                     containing the currently active system file.
  1344. _____________________________________________________________________*/
  1345.  
  1346. short utl_GetSysVol (void)
  1347.  
  1348. {
  1349.     
  1350.     short            vRefNum;                /* vol ref num */
  1351.  
  1352.     GetVRefNum(*(short*)(SysMap), &vRefNum);
  1353.     return vRefNum;
  1354. }
  1355.  
  1356. /*______________________________________________________________________
  1357.  
  1358.     utl_GetSysWD - Get WDRefNum of Blessed Folder.
  1359.     
  1360.     Exit:        function result = WDRefNum of Blessed Folder.
  1361. _____________________________________________________________________*/
  1362.  
  1363. short utl_GetSysWD (void)
  1364.  
  1365. {
  1366.     if (!GotSysEnviron) GetSysEnvirons();
  1367.     return TheWorld.sysVRefNum;
  1368. }
  1369.  
  1370. /*______________________________________________________________________
  1371.  
  1372.     utl_GetWindGD - Get the GDevice containing a window.
  1373.     
  1374.     Entry:    theWindow = pointer to window.
  1375.     
  1376.     Exit:        gd = handle to GDevice, or nil if no color QD.
  1377.                 screenRect = bounding rectangle of GDevice, or 
  1378.                     qd.screenBits.bounds if no color QD.
  1379.                 windRect = content rectangle of window, in global
  1380.                     coords.
  1381.                 hasMB = true if this screen contains the menu bar.
  1382.                 
  1383.     The routine determines the GDevice (screen) containing the maximum
  1384.     intersection with a window.  See TN 79.
  1385. _____________________________________________________________________*/
  1386.  
  1387. void utl_GetWindGD (WindowPtr theWindow, GDHandle *gd, 
  1388.     Rect *screenRect, Rect *windRect, Boolean *hasMB)
  1389.     
  1390. {
  1391.     GrafPtr            savePort;            /* saved grafport */
  1392.     Rect                sectRect;            /* intersection rect */
  1393.     GDHandle            curDevice;            /* current GDevice */
  1394.     GDHandle            dominantDevice;    /* dominant GDevice */
  1395.     long                sectArea;            /* intersection area */
  1396.     long                maxArea;                /* max intersection area */
  1397.     
  1398.     *windRect = theWindow->portRect;
  1399.     GetPort(&savePort);
  1400.     SetPort(theWindow);
  1401.     LocalToGlobal((Point*)&windRect->top);
  1402.     LocalToGlobal((Point*)&windRect->bottom);
  1403.     if (utl_HaveColor()) {
  1404.         windRect->top -= titleBarHeight;
  1405.         curDevice = GetDeviceList();
  1406.         maxArea = 0;
  1407.         dominantDevice = nil;
  1408.         while (curDevice) {
  1409.             if (TestDeviceAttribute(curDevice, screenDevice) &&
  1410.                 TestDeviceAttribute(curDevice, screenActive)) {
  1411.                 SectRect(windRect, &(**curDevice).gdRect, §Rect);
  1412.                 sectArea = (long)(sectRect.right - sectRect.left) * 
  1413.                     (long)(sectRect.bottom - sectRect.top);
  1414.                 if (sectArea > maxArea) {
  1415.                     maxArea = sectArea;
  1416.                     dominantDevice = curDevice;
  1417.                 }
  1418.             }
  1419.             curDevice = GetNextDevice(curDevice);
  1420.         }
  1421.         windRect->top += titleBarHeight;
  1422.         if (dominantDevice) {
  1423.             *gd = dominantDevice;
  1424.             *screenRect = (**dominantDevice).gdRect;
  1425.             *hasMB = dominantDevice == GetMainDevice();
  1426.         } else {
  1427.             *gd = nil;
  1428.             *screenRect = qd.screenBits.bounds;
  1429.             *hasMB = true;
  1430.         }    
  1431.     } else {
  1432.         *gd = nil;
  1433.         *screenRect = qd.screenBits.bounds;
  1434.         *hasMB = true;
  1435.     }
  1436.     SetPort(savePort);
  1437. }
  1438.  
  1439. /*______________________________________________________________________
  1440.  
  1441.     utl_GetVolFilCnt - Get the number of files on a volume.
  1442.     
  1443.     Entry:    volRefNum = volume reference number of volume.
  1444.     
  1445.     Exit:        function result = number of files on volume.
  1446.     
  1447.     For serdver volumes this function always returns 0.
  1448. _____________________________________________________________________*/
  1449.  
  1450. long utl_GetVolFilCnt (short volRefNum)
  1451.  
  1452. {
  1453.     HParamBlockRec        pBlock;        /* param block for PHBGetVInfo */
  1454.     
  1455.     pBlock.volumeParam.ioNamePtr = nil;
  1456.     pBlock.volumeParam.ioVRefNum = volRefNum;
  1457.     pBlock.volumeParam.ioVolIndex = 0;
  1458.     (void) PBHGetVInfo(&pBlock, false);
  1459.     return pBlock.volumeParam.ioVFilCnt;
  1460. }
  1461.  
  1462. /*______________________________________________________________________
  1463.  
  1464.     utl_HaveColor - Determine if system has color QuickDraw.
  1465.  
  1466.     Exit:        function result = true if we have color QD.
  1467. _____________________________________________________________________*/
  1468.  
  1469. Boolean utl_HaveColor (void)
  1470.  
  1471. {
  1472.     if (!GotSysEnviron) GetSysEnvirons();
  1473.     return TheWorld.hasColorQD;
  1474. }
  1475.  
  1476. /*______________________________________________________________________
  1477.  
  1478.     utl_HaveSound - Determine if system has the Sound Manager.
  1479.  
  1480.     Exit:        function result = true if we have sound.
  1481. _____________________________________________________________________*/
  1482.  
  1483. Boolean utl_HaveSound (void)
  1484.  
  1485. {
  1486.     if (!GotSysEnviron) GetSysEnvirons();
  1487.     return (TheWorld.systemVersion >= 0x0602);
  1488. }
  1489.  
  1490. /*______________________________________________________________________
  1491.  
  1492.     utl_HGetState - Get Memory Manager Flag Byte
  1493.     
  1494.     Entry:    h = handle.
  1495.     
  1496.     Exit:        function result = Flag byte.
  1497.                 
  1498.     This routine is identical to the standard HGetState Memory Manager
  1499.     trap, except it also works with the 64K ROM.
  1500. _____________________________________________________________________*/
  1501.  
  1502. char utl_HGetState (Handle h)
  1503.  
  1504. {
  1505.     static short    hgs = 2;        /* 0 if HGetState does not exist
  1506.                                             1 if HGetState exists
  1507.                                             2 if we don't yet know (first call) */
  1508.     
  1509.     /* Find out whether the HGetState trap is implemented if this is 
  1510.         the first call. */
  1511.     
  1512.     if (hgs == 2) {
  1513.         if (!GotSysEnviron) GetSysEnvirons();
  1514.         if (TheWorld.machineType < 0) {
  1515.             hgs = false;
  1516.         } else {
  1517.             hgs = (NGetTrapAddress(_HGetState & 0x3ff, OSTrap) == 
  1518.                 NGetTrapAddress(_Unimplemented & 0x3ff, OSTrap)) ? 0 : 1;
  1519.         }
  1520.     }
  1521.     
  1522.     /* If HGetState exists, call it, else get the flag bytes from the
  1523.         top byte of the master pointer. */
  1524.         
  1525.     if (hgs) {
  1526.         return HGetState(h);
  1527.     } else {
  1528.         return *(char*)h;
  1529.     }
  1530. }
  1531.  
  1532. /*______________________________________________________________________
  1533.  
  1534.     utl_HSetState - Set Memory Manager Flag Byte
  1535.     
  1536.     Entry:    h = handle.
  1537.                 flags = flag byte.
  1538.                 
  1539.     This routine is identical to the standard HSetState Memory Manager
  1540.     trap, except it also works with the 64K ROM.
  1541. _____________________________________________________________________*/
  1542.  
  1543. void utl_HSetState (Handle h, char flags)
  1544.  
  1545. {
  1546.     static short    hss = 2;        /* 0 if HSetState does not exist
  1547.                                             1 if HSetState exists
  1548.                                             2 if we don't yet know (first call) */
  1549.     
  1550.     /* Find out whether the HGetState trap is implemented if this is 
  1551.         the first call. */
  1552.     
  1553.     if (hss == 2) {
  1554.         if (!GotSysEnviron) GetSysEnvirons();
  1555.         if (TheWorld.machineType < 0) {
  1556.             hss = false;
  1557.         } else {
  1558.             hss = (NGetTrapAddress(_HSetState & 0x3ff, OSTrap) == 
  1559.                 NGetTrapAddress(_Unimplemented & 0x3ff, OSTrap)) ? 0 : 1;
  1560.         }
  1561.     }
  1562.     
  1563.     /* If HSetState exists, call it, else set the flag bytes in the
  1564.         top byte of the master pointer. */
  1565.         
  1566.     if (hss) {
  1567.         HSetState(h, flags);
  1568.     } else {
  1569.         *(char*)h = flags;
  1570.     }
  1571. }
  1572.  
  1573. /*______________________________________________________________________
  1574.  
  1575.     utl_InitSpinCursor - Initialize animated cursor.
  1576.     
  1577.     Entry:    cursArray = array of handles to cursors.
  1578.                 numCurs = number of cursors to rotate.
  1579.                 tickInterval = interval between cursor rotations.
  1580. _____________________________________________________________________*/
  1581.  
  1582. void utl_InitSpinCursor (CursHandle *cursArray, short numCurs, 
  1583.     short tickInterval)
  1584.  
  1585. {
  1586.     CursHandle        h;
  1587.  
  1588.     CursArray = cursArray;
  1589.     CurCurs = 0;
  1590.     NumCurs = numCurs;
  1591.     TickInterval = tickInterval;
  1592.     LastTick = TickCount();
  1593.     h = *cursArray;
  1594.     SetCursor(*h);
  1595. }
  1596.  
  1597. /*______________________________________________________________________
  1598.  
  1599.     utl_InteractionPermitted - Check to See if User Interaction is Permitted.
  1600.     
  1601.     Exit:        function result = true if user interaction is permitted.
  1602.     
  1603.     This function checks the various rules concerning Apple event user
  1604.     interaction, as specified in IM VI pp 6-51 through 6-54.
  1605.     
  1606.     The function returns true if the system does not support Apple events,
  1607.     or if there is no current Apple event.
  1608. _____________________________________________________________________*/
  1609.  
  1610. Boolean utl_InteractionPermitted (void)
  1611.  
  1612. {
  1613.     AppleEvent            event;            /* the current Apple event */
  1614.     DescType                typeCode;        /* descriptor type code */
  1615.     Size                    actualSize;        /* actual size of field data */
  1616.     short                    interact;        /* event interaction level */
  1617.     short                    source;            /* event source (see AppleEvents.h) */
  1618.     AEInteractAllowed    level;            /* permitted interaction level */
  1619.  
  1620.     if (!utl_GestaltFlag(gestaltAppleEventsAttr, 
  1621.         gestaltAppleEventsPresent)) return true;
  1622.     if (AEGetTheCurrentEvent(&event) || 
  1623.         event.descriptorType == typeNull) return true;
  1624.     if (AEGetAttributePtr(&event, keyInteractLevelAttr, typeShortInteger,
  1625.         &typeCode, (Ptr)&interact, sizeof(short), &actualSize)) return true;
  1626.     if (interact & kAENeverInteract) return false;
  1627.     if (AEGetAttributePtr(&event, keyEventSourceAttr, typeShortInteger,
  1628.         &typeCode, (Ptr)&source, sizeof(short), &actualSize)) return true;
  1629.     if (source <= kAESameProcess) return true;
  1630.     if (AEGetInteractionAllowed(&level)) return true;
  1631.     if (source == kAELocalProcess && level >= kAEInteractWithLocal) return true;
  1632.     return level == kAEInteractWithAll;
  1633. }
  1634.  
  1635. /*______________________________________________________________________
  1636.  
  1637.     utl_InvalGrow - Invalidate Grow Icon.
  1638.     
  1639.     Entry:            theWindow = pointer to window.
  1640.     
  1641.     This routine should be called before and after calling SizeWindow
  1642.     for windows with grow icons.
  1643. _____________________________________________________________________*/
  1644.  
  1645. void utl_InvalGrow (WindowPtr theWindow)
  1646.  
  1647. {
  1648.     Rect            r;            /* rect to be invalidated */
  1649.     
  1650.     r = theWindow->portRect;
  1651.     r.top = r.bottom - 15;
  1652.     r.left = r.right - 15;
  1653.     InvalRect(&r);
  1654. }
  1655.  
  1656. /*______________________________________________________________________
  1657.  
  1658.     utl_IsDAWindow - Check to see if a window is a DA.
  1659.     
  1660.     Entry:    theWindow = pointer to dialog window.
  1661.                 
  1662.     
  1663.     Exit:        function result = true if DA window.
  1664. _____________________________________________________________________*/
  1665.  
  1666. Boolean utl_IsDAWindow (WindowPtr theWindow)
  1667.  
  1668. {
  1669.     return ((WindowPeek)theWindow)->windowKind < 0;
  1670. }
  1671.  
  1672. /*______________________________________________________________________
  1673.  
  1674.     utl_IsLaser - Check Printer for LaserWriter.
  1675.     
  1676.     Entry:    hPrint = handle to print record.
  1677.     
  1678.     Exit:        function result = true if LaserWriter.
  1679.     
  1680. _____________________________________________________________________*/
  1681.  
  1682. Boolean utl_IsLaser (THPrint hPrint)
  1683.  
  1684. {
  1685.     unsigned char    wDev;                /* printer device */
  1686.  
  1687.     wDev = (**hPrint).prStl.wDev >> 8;
  1688.     return wDev==3 || wDev==4;
  1689. }
  1690.  
  1691. /*______________________________________________________________________
  1692.  
  1693.     utl_KillAllProcesses - Kill All Processes.
  1694.     
  1695.     Entry:    idleProc = pointer to AppleEvent idle proc.
  1696.     
  1697.     Exit:        function result = error code.
  1698.                 allKilled = true if all other processes have been killed.
  1699.                 
  1700.     System 7.0 only.
  1701.     
  1702.     Alll processes are killed except for the current process.
  1703.     Users are given the oportunity to save unsaved docs.
  1704.     
  1705.     allKilled will be false if the user cancels an alert that is presented
  1706.     when an app is asked to quit, then switches to some other process
  1707.     without quiting the app.
  1708. _____________________________________________________________________*/
  1709.  
  1710. OSErr utl_KillAllProcesses (utl_AEIdleProcPtr idleProc, Boolean *allKilled)
  1711.  
  1712. {
  1713.     ProcessSerialNumber    psn;                /* psn of system process */
  1714.     AppleEvent                message;            /* quit AppleEvent */
  1715.     AEAddressDesc            targetAddr;        /* target address */
  1716.     OSErr                        rCode;            /* result code */
  1717.     short                        count;            /* process count */
  1718.     
  1719.     psn.highLongOfPSN = 0;
  1720.     psn.lowLongOfPSN = kSystemProcess;
  1721.     if (rCode = AECreateDesc(typeProcessSerialNumber, (Ptr)&psn, 
  1722.         sizeof(ProcessSerialNumber), &targetAddr)) return rCode;
  1723.     if (rCode = AECreateAppleEvent(kCoreEventClass, kAEQuitAll,
  1724.         &targetAddr, kAutoGenerateReturnID, kAnyTransactionID, &message)) goto exit2;
  1725.     if (rCode = AESend(&message, nil, kAEWaitReply | kAECanInteract, kAENormalPriority,
  1726.         kAEDefaultTimeout, (IdleProcPtr)idleProc, nil)) goto exit1;
  1727.     if (rCode = utl_CountProcesses(&count)) goto exit1;
  1728.     *allKilled = count == 1;
  1729.     rCode = noErr;
  1730. exit1:
  1731.     AEDisposeDesc(&message);
  1732. exit2:
  1733.     AEDisposeDesc(&targetAddr);
  1734.     return rCode;
  1735. }
  1736.  
  1737. /*______________________________________________________________________
  1738.  
  1739.     utl_KillOneProcess - Kill One Process.
  1740.     
  1741.     Entry:    idleProc = pointer to AppleEvent idle proc.
  1742.                 psn = process serial number of process to be killed.
  1743.                 
  1744.     Exit:        function result = error code.
  1745.     
  1746.     System 7.0 only. The user is give an opportunity to save unsaved docs.
  1747.     
  1748.     The target process does not have to be AppleEvent-aware! It may even
  1749.     be a backbround-only process.
  1750. _____________________________________________________________________*/
  1751.  
  1752. OSErr utl_KillOneProcess (utl_AEIdleProcPtr idleProc, ProcessSerialNumber *psn)
  1753.  
  1754. {
  1755.     AppleEvent                message;            /* quit AppleEvent */
  1756.     AEAddressDesc            targetAddr;        /* target address */
  1757.     ProcessInfoRec            info;                /* process info */
  1758.     OSErr                        rCode;            /* result code */
  1759.     EventRecord                theEvent;        /* event record */
  1760.     long                        sleepTime;        /* sleep time */
  1761.     RgnHandle                mouseRgn;        /* mouse region */
  1762.     
  1763.     if (rCode = AECreateDesc(typeProcessSerialNumber, (Ptr)psn, 
  1764.         sizeof(ProcessSerialNumber), &targetAddr)) return rCode;
  1765.     if (rCode = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication,
  1766.         &targetAddr, kAutoGenerateReturnID, kAnyTransactionID, &message)) goto exit2;
  1767.     rCode = AESend(&message, nil, kAENoReply | kAECanInteract, kAENormalPriority,
  1768.         kAEDefaultTimeout, (IdleProcPtr)idleProc, nil);
  1769.     if (rCode && rCode != procNotFound) goto exit1;
  1770.     info.processInfoLength = sizeof(ProcessInfoRec);
  1771.     info.processName = nil;
  1772.     info.processAppSpec = nil;
  1773.     do {
  1774.         GetNextEvent(everyEvent, &theEvent);
  1775.         (*idleProc)(&theEvent, &sleepTime, &mouseRgn);
  1776.     } while (!GetProcessInformation(psn, &info));
  1777.     rCode = noErr;
  1778. exit1:
  1779.     AEDisposeDesc(&message);
  1780. exit2:
  1781.     AEDisposeDesc(&targetAddr);
  1782.     return rCode;
  1783. }
  1784.  
  1785. /*______________________________________________________________________
  1786.  
  1787.     utl_LocateFinder - Locate the Finder.
  1788.                 
  1789.     Exit:        function result = error code.
  1790.                 finderFound = true if Finder running.
  1791.                 finderFSpec = FSpec of Finder, if Finder running. Undefined
  1792.                     if Finder not running.
  1793.     
  1794.     System 7.0 only.
  1795. _____________________________________________________________________*/
  1796.  
  1797. OSErr utl_LocateFinder (Boolean *finderFound, FSSpec *finderFSpec)
  1798.     
  1799. {
  1800.     OSErr                        rCode;                /* result code */
  1801.     ProcessInfoRec            info;                    /* process info */
  1802.     FSSpec                    fSpec;                /* process file spec */
  1803.     ProcessSerialNumber    psn;                    /* process serial number */
  1804.  
  1805.     *finderFound = false;
  1806.     info.processInfoLength = sizeof(ProcessInfoRec);
  1807.     info.processName = nil;
  1808.     info.processAppSpec = &fSpec;
  1809.     psn.highLongOfPSN = 0;
  1810.     psn.lowLongOfPSN = kNoProcess;
  1811.     while (!(rCode = GetNextProcess(&psn))) {
  1812.         if (rCode = GetProcessInformation(&psn, &info)) return rCode;
  1813.         if (info.processType == 'FNDR' && info.processSignature == 'MACS') {
  1814.             *finderFound = true;
  1815.             *finderFSpec = fSpec;
  1816.             return noErr;
  1817.         }
  1818.     }
  1819.     if (rCode == procNotFound) rCode = noErr;
  1820.     return rCode;
  1821. }
  1822.  
  1823. /*______________________________________________________________________
  1824.  
  1825.     utl_LockControls - Lock Window Controls
  1826.     
  1827.     Entry:    theWindow = pointer to window.
  1828.     
  1829.     This routine moves all the control records in a window high and
  1830.     locks them.  It should be called immediately after creating a new
  1831.     window, and before drawing it.  It works around errors in the Control
  1832.     Manager which showed up when I was testing with TMON's heap scramble and
  1833.     purge option.
  1834. _____________________________________________________________________*/
  1835.  
  1836. void utl_LockControls (WindowPtr theWindow)
  1837.  
  1838. {
  1839.     ControlHandle        theControl;        /* handle to control */
  1840.  
  1841.     theControl = ((WindowPeek)theWindow)->controlList;
  1842.     while (theControl) {
  1843.         MoveHHi((Handle)theControl);
  1844.         HLock((Handle)theControl);
  1845.         theControl = (**theControl).nextControl;
  1846.     }
  1847. }
  1848.  
  1849. /*_____________________________________________________________________
  1850.  
  1851.     utl_ModalDialog - Present a Modal Dialog
  1852.  
  1853.     Entry:    dlogID = dialog ID.
  1854.                 filterProc = pointer to filter proc.
  1855.                 defaultItem = item number of default button, or 0 if none.
  1856.                 cancelItem = item number of cancel button, or 0 if none.
  1857.                 parameters following "theDialog" = list of useritem handlers, in
  1858.                     the same order as the useritems in the dialog.
  1859.                     
  1860.     Exit:        itemHit = item number of enabled item.
  1861.                 theDialog = pointer to the dialog.
  1862.     
  1863.     This function centers the dialog on the main screen before presenting it,
  1864.     and it offers an easy way to plug in your useritem handlers.  
  1865.     
  1866.     If requested, Return or Enter is treated the same as a click on the
  1867.     default button.
  1868.     
  1869.     If requested, Command/Period or the Escape key is treated the same as a
  1870.     click on the Cancel button.
  1871.     
  1872.     The caller must dispose of the dialog.
  1873. _____________________________________________________________________*/
  1874.  
  1875. void utl_ModalDialog (short dlogID, ModalFilterProcPtr filterProc, 
  1876.     short defaultItem, short cancelItem, short *itemHit, DialogPtr *theDialog, ...)
  1877.  
  1878. {
  1879.     va_list            ap;                /* points to list of useritem handlers */
  1880.     Handle            hdlog;            /* handle to dialog */
  1881.     DialogPtr        dlog;                /* pointer to dialog */
  1882.     short                numItems;        /* number of items in dialog */
  1883.     short                i;                    /* loop index */
  1884.     short                itemType;        /* item type */
  1885.     Handle            item;                /* handle to item */
  1886.     Rect                box;                /* item rectangle */
  1887.     
  1888.     InitCursor();
  1889.     va_start(ap, theDialog);
  1890.     hdlog = GetResource('DLOG', dlogID);
  1891.     HLock(hdlog);
  1892.     utl_CenterDlogRect(*(Rect**)hdlog, true);
  1893.     HUnlock(hdlog);
  1894.     dlog = GetNewDialog(dlogID, nil, (WindowPtr)-1);
  1895.     numItems = **(short**)(((DialogPeek)dlog)->items) + 1;
  1896.     IBeamHandle = GetCursor(iBeamCursor);
  1897.     for (i = 1; i <= numItems; i++) {
  1898.         GetDItem(dlog, i, &itemType, &item, &box);
  1899.         if ((itemType & 0x7f) == userItem) {
  1900.             item = va_arg(ap, Handle);
  1901.             SetDItem(dlog, i, itemType, item, &box);
  1902.         }
  1903.     }
  1904.     va_end(ap);
  1905.     ShowWindow((WindowPtr)dlog);
  1906.     Filter = filterProc;
  1907.     DefaultItem = defaultItem;
  1908.     CancelItem = cancelItem;
  1909.     ModalDialog(MetaFilter, itemHit);
  1910.     *theDialog = dlog;
  1911. }
  1912.  
  1913. /*_____________________________________________________________________
  1914.  
  1915.     utl_ModalDialogContinue - Continue Modal Dialog
  1916.  
  1917.     Entry:    filterProc = pointer to filter proc.
  1918.                 defaultItem = item number of default button, or 0 if none.
  1919.                 cancelItem = item number of cancel button, or 0 if none.
  1920.                     
  1921.     Exit:        itemHit = item number of enabled item.
  1922.     
  1923.     This function should be called to continue a modal dialog if the dialog
  1924.     was initially presented via a call to utl_ModalDialog.
  1925. _____________________________________________________________________*/
  1926.  
  1927. void utl_ModalDialogContinue (ModalFilterProcPtr filterProc,
  1928.     short defaultItem, short cancelItem, short *itemHit)
  1929.     
  1930. {
  1931.     Filter = filterProc;
  1932.     DefaultItem = defaultItem;
  1933.     CancelItem = cancelItem;
  1934.     ModalDialog(MetaFilter, itemHit);
  1935. }
  1936.  
  1937. /*_____________________________________________________________________
  1938.  
  1939.     utl_OutlineDefaultButton - Outline Default Button.
  1940.  
  1941.     Entry:    theWindow = pointer to dialog window.
  1942.                 itemNo = item number of outline useritem.
  1943.                 
  1944.     This routine is for use as a useritem handler to outline default
  1945.     buttons in dialogs.  The default button must be the first item
  1946.     in the dialog item list.
  1947. _____________________________________________________________________*/
  1948.  
  1949. pascal void utl_OutlineDefaultButton (WindowPtr theWindow, short itemNo)
  1950.  
  1951. {
  1952. #pragma unused (itemNo)
  1953.  
  1954.     short                itemType;        /* item type */
  1955.     Handle            item;                /* handle to item */
  1956.     Rect                box;                /* item rectangle */
  1957.  
  1958.     GetDItem(theWindow, ok, &itemType, &item, &box);
  1959.     InsetRect(&box, -4, -4);
  1960.     PenSize(3, 3);
  1961.     FrameRoundRect(&box, 16, 16);
  1962.     PenSize(1, 1);
  1963. }    
  1964.  
  1965. /*______________________________________________________________________
  1966.  
  1967.     utl_PlotSmallIcon - Draw a small icon.
  1968.     
  1969.     Entry:    theRect = rectangle in which to draw the small icon.
  1970.                 theHandle = handle to small icon.
  1971.                     
  1972.     For best results, the rectangle should be exactly 16 pixels square.
  1973. _____________________________________________________________________*/
  1974.  
  1975. void utl_PlotSmallIcon (Rect *theRect, Handle theHandle)
  1976.  
  1977. {
  1978.     BitMap        srcBits;            /* Source bitmap for CopyBits */
  1979.     
  1980.     MoveHHi(theHandle);
  1981.     HLock(theHandle);
  1982.     srcBits.baseAddr = *theHandle;
  1983.     srcBits.rowBytes = 2;
  1984.     SetRect(&srcBits.bounds, 0, 0, 16, 16);
  1985.     CopyBits(&srcBits, &qd.thePort->portBits, &srcBits.bounds, theRect,
  1986.         srcCopy, nil);
  1987.     HUnlock(theHandle);
  1988. }
  1989.  
  1990. /*______________________________________________________________________
  1991.  
  1992.     utl_PlugParams - Plug parameters into message.
  1993.     
  1994.     Entry:    line1 = input line.
  1995.                 p0, p1, p2, p3 = parameters.
  1996.                     
  1997.     Exit:        line2 = output line.
  1998.                     
  1999.     This routine works just like the toolbox routine ParamText.
  2000.     The input line may contain place-holders ^0, ^1, ^2, and ^3, 
  2001.     which are replaced by the parameters p0-p3.  The input line
  2002.     must not contain any other ^ characters.  The input and output lines
  2003.     may not be the same string.  Pass nil for parameters which don't
  2004.     occur in line1.  If the output line exceeds 255 characters it's
  2005.     truncated.
  2006. _____________________________________________________________________*/
  2007.  
  2008. void utl_PlugParams (Str255 line1, Str255 line2, Str255 p0, 
  2009.     Str255 p1, Str255 p2, Str255 p3)
  2010.  
  2011. {
  2012.     unsigned char        *in;            /* pointer to cur pos in input line */
  2013.     unsigned char        *out;            /* pointer to cur pos in output line */
  2014.     unsigned char        *inEnd;        /* pointer to end of input line */
  2015.     unsigned char        *outEnd;        /* pointer to end of output line */
  2016.     unsigned char        *param;        /* pointer to param to be plugged */
  2017.     short                    len;            /* length of param */
  2018.     
  2019.     in = line1+1;
  2020.     out = line2+1;
  2021.     inEnd = line1 + 1 + *line1;
  2022.     outEnd = line2 + 256;
  2023.     while (in < inEnd ) {
  2024.         if (*in == '^') {
  2025.             in++;
  2026.             if (in >= inEnd) break;
  2027.             switch (*in++) {
  2028.                 case '0':
  2029.                     param = p0;
  2030.                     break;
  2031.                 case '1':
  2032.                     param = p1;
  2033.                     break;
  2034.                 case '2':
  2035.                     param = p2;
  2036.                     break;
  2037.                 case '3':
  2038.                     param = p3;
  2039.                     break;
  2040.                 default:
  2041.                     continue;
  2042.             }
  2043.             if (!param) continue;
  2044.             len = *param;
  2045.             if (out + len > outEnd) len = outEnd - out;
  2046.             memcpy(out, param+1, len);
  2047.             out += len;
  2048.         } else {
  2049.             if (out >= outEnd) break;
  2050.             *out++ = *in++;
  2051.         }
  2052.     }
  2053.     *line2 = out - (line2+1);
  2054. }
  2055.  
  2056. /*______________________________________________________________________
  2057.  
  2058.     utl_RedrawMenuBar - Redraw Menu Bar.
  2059.     
  2060.     Entry:    mBarState = array of flags. Each flag is true if the
  2061.                     previous state of the corresponding menu was enabled.
  2062.                 nMenus = number of menus.
  2063.                 
  2064.     Exit:        Menu bar redrawn only if some menu has changed state.
  2065.                 mBarState array updated.
  2066. _____________________________________________________________________*/
  2067.  
  2068. void utl_RedrawMenuBar (Boolean mBarState[], short nMenus)
  2069.  
  2070. {
  2071.     char                        *pMenuList;                /* pointer into menu list */
  2072.     char                        *pMenuListEnd;            /* pointer to end of menu list */
  2073.     Boolean                    reDrawMenuBar;            /* true if menu bar must be redrawn */
  2074.     short                        menuIndex;                /* index into menu list */
  2075.     MenuHandle                hMenu;                    /* handle to menu */
  2076.     Boolean                    enabled;                    /* true if menu enabled */
  2077.  
  2078.     pMenuList = **(char***)MenuList;
  2079.     if (*(short*)pMenuList < 6*nMenus) return;
  2080.     pMenuListEnd = pMenuList + 6*nMenus;
  2081.     pMenuList += 6;
  2082.     reDrawMenuBar = false;
  2083.     menuIndex = 0;
  2084.     while (pMenuList <= pMenuListEnd) {
  2085.         hMenu = *(MenuHandle*)(pMenuList);
  2086.         enabled = (**hMenu).enableFlags & 1;
  2087.         if (enabled != mBarState[menuIndex]) {
  2088.             reDrawMenuBar = true;
  2089.             mBarState[menuIndex] = enabled;
  2090.         }
  2091.         pMenuList += 6;
  2092.         menuIndex++;
  2093.     }
  2094.     if (reDrawMenuBar) DrawMenuBar();
  2095. }
  2096.  
  2097. /*______________________________________________________________________
  2098.  
  2099.     utl_Restart - Restart
  2100.     
  2101.     Exit:        function result = error code.
  2102.  
  2103.     System 7 only. 
  2104.     
  2105.     Users are given the oportunity to save unsaved docs.
  2106. _____________________________________________________________________*/
  2107.  
  2108. OSErr utl_Restart (void)
  2109.  
  2110. {
  2111.     ProcessSerialNumber    psn;                /* psn of system process */
  2112.     AppleEvent                message;            /* restart AppleEvent */
  2113.     AEAddressDesc            targetAddr;        /* target address */
  2114.     OSErr                        rCode;            /* result code */
  2115.     
  2116.     psn.highLongOfPSN = 0;
  2117.     psn.lowLongOfPSN = kSystemProcess;
  2118.     if (rCode = AECreateDesc(typeProcessSerialNumber, (Ptr)&psn, 
  2119.         sizeof(ProcessSerialNumber), &targetAddr)) return rCode;
  2120.     if (rCode = AECreateAppleEvent(kCoreEventClass, kAERestart,
  2121.         &targetAddr, kAutoGenerateReturnID, kAnyTransactionID, &message)) goto exit2;
  2122.     if (rCode = AESend(&message, nil, kAENoReply | kAECanInteract, kAENormalPriority,
  2123.         kAEDefaultTimeout, nil, nil)) goto exit1;
  2124.     rCode = noErr;
  2125. exit1:
  2126.     AEDisposeDesc(&message);
  2127. exit2:
  2128.     AEDisposeDesc(&targetAddr);
  2129.     return rCode;
  2130. }
  2131.  
  2132. /*______________________________________________________________________
  2133.  
  2134.     utl_RestoreWindowPos - Restore Window Position.
  2135.     
  2136.     Entry:    theWindow = pointer to window.
  2137.                 userState = saved user state rectangle for the window.
  2138.                 zoomed = true if window in zoomed state when saved.
  2139.                 offset = pixel offset used in DragRect calls.
  2140.                 computeStdState = pointer to function to compute standard state.
  2141.                 computeDefState = pointer to function to compute default state.
  2142.     
  2143.     Exit:        window position, size, and zoom state restored.
  2144.                 userState = new user state.
  2145.                 
  2146.     See HIN 6: "When reopening a movable window, check its saved 
  2147.     position.  If the window is in a position to which the user could
  2148.     have dragged it, then leave it there.  If the window can be zoomed
  2149.     and was in the zoomed state when it was last closed, put it in the
  2150.     zoomed state again.  (Note that the current and previous zoomed states
  2151.     are not necessarily the same, since the window may be reopened on a
  2152.     different monitor.)  If the window is not in a position to which the
  2153.     user could have dragged it, then it must be relocated, so use the
  2154.     default location.  However, do not automatically use the default size
  2155.     when using the default location; if the entire window would be visible
  2156.     using the default location and stored size, then use the stored size."
  2157.     
  2158.     The "offset" parameter is usually 4.  When initializing the boundary rectangle
  2159.     for DragWindow calls, normally the boundary rectangle of the desktop gray
  2160.     region is inset by 4 pixels.  If some value other than 4 is used, it should
  2161.     be passed to RestoreWindowPos as the "offset" parameter.
  2162.     
  2163.     The computeStdState function is passed a pointer to the window.  Given
  2164.     the userState in the window zoom info, it must compute the standard
  2165.     (zoom) state in the window zoom info.  This is an application-dependent
  2166.     function.
  2167.     
  2168.     The computeDefState function must determine the default position and
  2169.     size of a new window, and return the result as a rectangle.  This may
  2170.     involve invocation of a staggering algorithm or some other algorithm.
  2171.     This is an application-dependent function.
  2172. _____________________________________________________________________*/
  2173.  
  2174. void utl_RestoreWindowPos (WindowPtr theWindow, Rect *userState, 
  2175.     Boolean zoomed, short offset,
  2176.     utl_ComputeStdStatePtr computeStdState,
  2177.     utl_ComputeDefStatePtr computeDefState)
  2178.  
  2179. {
  2180.     WindowPeek        w;                    /* window pointer */
  2181.     short                userHeight;        /* height of userState */
  2182.     short                userWidth;        /* width of userState */
  2183.     Rect                r;                    /* scratch rectangle */
  2184.     RgnHandle        rgn;                /* scratch region */
  2185.     Rect                stdState;        /* standard state */
  2186.     short                windHeight;        /* window height */
  2187.     short                windWidth;        /* window width */
  2188.  
  2189.     w = (WindowPeek)theWindow;
  2190.     if (!utl_CouldDrag(userState, offset)) {
  2191.         userHeight = userState->bottom - userState->top;
  2192.         userWidth = userState->right - userState->left;
  2193.         (*computeDefState)(theWindow, userState);
  2194.         if (!zoomed) {
  2195.             r = *userState;
  2196.             r.bottom = r.top + userHeight;
  2197.             r.right = r.left + userWidth;
  2198.             r.top -= titleBarHeight;
  2199.             InsetRect(&r, -1, -1);
  2200.             rgn = NewRgn();
  2201.             RectRgn(rgn, &r);
  2202.             DiffRgn(rgn, *(RgnHandle*)GrayRgn, rgn);
  2203.             if (EmptyRgn(rgn)) {
  2204.                 userState->bottom = userState->top + userHeight;
  2205.                 userState->right = userState->left + userWidth;
  2206.             }
  2207.             DisposeRgn(rgn);
  2208.         }
  2209.     }
  2210.     MoveWindow(theWindow, userState->left, userState->top, false);
  2211.     windHeight = userState->bottom - userState->top;
  2212.     windWidth = userState->right - userState->left;
  2213.     SizeWindow(theWindow, windWidth, windHeight, true);
  2214.     if (w->dataHandle && w->spareFlag) {
  2215.         (**((WStateData**)w->dataHandle)).userState = *userState;
  2216.         (*computeStdState)(theWindow);
  2217.         if (zoomed) {
  2218.             stdState = (**((WStateData**)w->dataHandle)).stdState;
  2219.             MoveWindow(theWindow, stdState.left, stdState.top, false);
  2220.             windHeight = stdState.bottom - stdState.top;
  2221.             windWidth = stdState.right - stdState.left;
  2222.             SizeWindow(theWindow, windWidth, windHeight, true);
  2223.         }
  2224.     }
  2225. }
  2226.  
  2227. /*______________________________________________________________________
  2228.  
  2229.     utl_ReviveFinder - Revive the Finder Process.
  2230.     
  2231.     Entry:    fSpec = Finder file spec.
  2232.     
  2233.     Exit:        function result = error code.
  2234.     
  2235.     System 7.0 only.
  2236.     
  2237.     This function can be used to bring the Finder back after it has
  2238.     been killed by a call to utl_KillAllProcesses.
  2239. _____________________________________________________________________*/
  2240.  
  2241. OSErr utl_ReviveFinder (FSSpec *fSpec)
  2242.  
  2243. {
  2244.     LaunchParamBlockRec    pBlock;        /* launch param block */
  2245.     OSErr                        rCode;        /* result code */
  2246.     short                        count;        /* counter */
  2247.     EventRecord                theEvent;    /* event record */
  2248.     
  2249.     pBlock.launchBlockID = extendedBlock;
  2250.     pBlock.launchEPBLength = extendedBlockLen;
  2251.     pBlock.launchFileFlags = 0;
  2252.     pBlock.launchControlFlags = launchContinue | launchNoFileFlags |
  2253.         launchDontSwitch;
  2254.     pBlock.launchAppSpec = fSpec;
  2255.     pBlock.launchAppParameters = nil;
  2256.     rCode = LaunchApplication(&pBlock);
  2257.     if (rCode) return rCode;
  2258.     count = 20;
  2259.     while (count--) GetNextEvent(everyEvent, &theEvent);
  2260.     return noErr;
  2261. }
  2262.  
  2263. /*______________________________________________________________________
  2264.  
  2265.     utl_Rom64 - Check to see if we have the old 64K ROM.
  2266.     
  2267.     Exit:        function result = true if 64K ROM.
  2268. _____________________________________________________________________*/
  2269.  
  2270. Boolean utl_Rom64 (void)
  2271.  
  2272. {
  2273.     return *(short*)ROM85 < 0;
  2274. }
  2275.  
  2276. /*______________________________________________________________________
  2277.  
  2278.     utl_SaveChangesAlert - Present Save Changes Alert.
  2279.     
  2280.     Entry:    tmpl = save changes message template.
  2281.                 dlogID = resource id of save changes message dialog.
  2282.                 filterProc = pointer to filter proc.
  2283.                 p0,p1,p2,p3 = parameters to plug into template.
  2284.                 
  2285.     Exit:        function result = item number of button selected.
  2286.                 
  2287.     The save changes message dialog must have:
  2288.     item 1 = Save button.
  2289.     item 2 = Cancel button.
  2290.     item 3 = Don't Save button.
  2291.     item 4 = note icon.
  2292.     item 5 = static text field with content "^0".
  2293.     item 6 = user item used to outline the OK button.
  2294.     
  2295.     This function adjusts the height of the alert and the static text
  2296.     field so that they are just high enough to contain the message.
  2297. _____________________________________________________________________*/
  2298.  
  2299. short utl_SaveChangesAlert (Str255 tmpl, short dlogID, 
  2300.     ModalFilterProcPtr filterProc, Str255 p0, Str255 p1,
  2301.     Str255 p2, Str255 p3)
  2302.  
  2303. {
  2304.     return MagicAlert(tmpl, dlogID, filterProc, 
  2305.         p0, p1, p2, p3, 3, 5, 6, 1, 2);
  2306. }
  2307.  
  2308. /*______________________________________________________________________
  2309.  
  2310.     utl_SaveChangesAlertRez - Present Save Changes Alert.
  2311.     
  2312.     Entry:    rezID = resource id of STR# resource containing message
  2313.                     template.
  2314.                 index = index in STR# resource of message template.
  2315.                 dlogID = resource id of message dialog.
  2316.                 filterProc = pointer to filter proc.
  2317.                 p0, p1, p2, p3 = parameters to plug into template.
  2318.                 
  2319.     Exit:        function result = item number of button selected.
  2320. _____________________________________________________________________*/
  2321.  
  2322. short utl_SaveChangesAlertRez (short rezID, short index, short dlogID,
  2323.     ModalFilterProcPtr filterProc, 
  2324.     Str255 p0, Str255 p1, Str255 p2, Str255 p3)
  2325.     
  2326. {
  2327.     Str255            tmpl;            /* message template */
  2328.     
  2329.     GetIndString(tmpl, rezID, index);
  2330.     return utl_SaveChangesAlert(tmpl, dlogID, filterProc, p0, p1, p2, p3);
  2331. }
  2332.  
  2333. /*______________________________________________________________________
  2334.  
  2335.     utl_SaveWindowPos - Save Window Position.
  2336.     
  2337.     Entry:    theWindow = window pointer.
  2338.     
  2339.     Exit:        userState = user state rectangle of the window.
  2340.                 zoomed = true if window zoomed.
  2341.                 
  2342.     See HIN 6: "Before closing a movable window, check to see if its
  2343.     location or size have changed.  If so, save the new location and
  2344.     size.  If the window can be zoomed, save the user state and also 
  2345.     save whether or not the window is in the zoomed (standard) sate."
  2346.     
  2347.     We assume in this routine that the caller has already kept track
  2348.     of the fact that this window's location or size has changed, and that
  2349.     we do indeed need to save the location and size.
  2350.     
  2351.     This routine only works if the window's origin has not been offset.
  2352. _____________________________________________________________________*/
  2353.  
  2354. void utl_SaveWindowPos (WindowPtr theWindow, Rect *userState, Boolean *zoomed)
  2355.  
  2356. {
  2357.     GrafPtr        savedPort;        /* saved grafport */
  2358.     WindowPeek    w;                    /* window pointer */
  2359.     Rect            curState;        /* current window rect, global coords */
  2360.     Rect            stdState;        /* standard (zoom) rect, global coords */
  2361.     Point            p;                    /* scratch point */
  2362.     Rect            r;                    /* scratch rect */
  2363.     
  2364.     GetPort(&savedPort);
  2365.     SetPort(theWindow);
  2366.     SetPt(&p, 0, 0);
  2367.     LocalToGlobal(&p);
  2368.     curState = theWindow->portRect;
  2369.     OffsetRect(&curState, p.h, p.v);
  2370.     w = (WindowPeek)theWindow;
  2371.     if (w->dataHandle && w->spareFlag) {
  2372.         /* This window supports zooming */
  2373.         /* Determine if window is zoomed.  The criteria is that both the
  2374.             top left and bottom right corners of the current window rectangle
  2375.             and the standard (zoom) rectangle must be within 7 pixels of each
  2376.             other.  This is the same algorithm as the one used by the standard
  2377.             system window definition function. */
  2378.         *zoomed = false;
  2379.         stdState = (**((WStateData**)w->dataHandle)).stdState;
  2380.         SetPt(&p, curState.left, curState.top);
  2381.         SetRect(&r, stdState.left, stdState.top, stdState.left, stdState.top);
  2382.         InsetRect(&r, -7, -7);
  2383.         if (PtInRect(p, &r)) {
  2384.             SetPt(&p, curState.right, curState.bottom);
  2385.             SetRect(&r, stdState.right, stdState.bottom, stdState.right,
  2386.                 stdState.bottom);
  2387.             InsetRect(&r, -7, -7);
  2388.             *zoomed = PtInRect(p, &r);
  2389.         }
  2390.         if (*zoomed) {
  2391.             *userState = (**((WStateData**)w->dataHandle)).userState;
  2392.         } else {
  2393.             *userState = curState;
  2394.         }
  2395.     } else {
  2396.         /* This window does not support zooming. */
  2397.         *zoomed = false;
  2398.         *userState = curState;
  2399.     }
  2400.     SetPort(savedPort);
  2401. }
  2402.  
  2403. /*______________________________________________________________________
  2404.  
  2405.     utl_ScaleFontSize - Scale Font Size
  2406.     
  2407.     Entry:    theFontNum = font number.
  2408.                 theFontSize = nominal font size.
  2409.                 percent = percent change in size.
  2410.                 laser = true if laserwriter.
  2411.     
  2412.     Exit:        function result = scaled font size.
  2413.                 
  2414.     The nominal font size is multiplied by the percentage,
  2415.     then truncated.  For non-laserwriters it is then rounded down
  2416.     to the nearest font size which is available in that true size,
  2417.     without font manager scaling, or which can be generated by doubling
  2418.     an existing font size.
  2419. _____________________________________________________________________*/
  2420.  
  2421. short utl_ScaleFontSize (short theFontNum, short theFontSize, short percent,
  2422.     Boolean laser)
  2423.     
  2424. {
  2425.     short            nSize;                /* new size */
  2426.     short            x;                        /* new test size */
  2427.     
  2428.     nSize = theFontSize * percent / 100;
  2429.     if (!laser) {
  2430.         x = nSize;
  2431.         while (x > 0) {
  2432.             if (RealFont(theFontNum, x)) break;
  2433.             if (!(x&1) && RealFont(theFontNum, x>>1)) break;
  2434.             x--;
  2435.         }
  2436.         if (x) nSize = x;
  2437.     }
  2438.     return nSize;
  2439. }
  2440.  
  2441. /*______________________________________________________________________
  2442.  
  2443.     utl_SetDialogControlValue - Set Dialog Control Value.
  2444.     
  2445.     Entry:    theDialog = pointer to dialog record.
  2446.                 itemNo = item number of control.
  2447.                 val = new value for control.
  2448. _____________________________________________________________________*/
  2449.  
  2450. void utl_SetDialogControlValue (DialogPtr theDialog, short itemNo, short val)
  2451.  
  2452. {
  2453.     short        itemType;            /* item type */
  2454.     Handle    item;                    /* handle to item */
  2455.     Rect        box;                    /* item rectangle */
  2456.  
  2457.     GetDItem(theDialog, itemNo, &itemType, &item, &box);
  2458.     SetCtlValue((ControlHandle)item, val);
  2459. }
  2460.  
  2461. /*______________________________________________________________________
  2462.  
  2463.     utl_SetDialogNumericText - Set Dialog Numeric Text Item.
  2464.     
  2465.     Entry:    theDialog = pointer to dialog record.
  2466.                 itemNo = item number of statText or editText item.
  2467.                 theNum = the number.
  2468. _____________________________________________________________________*/
  2469.  
  2470. void utl_SetDialogNumericText (DialogPtr theDialog, short itemNo, short theNum)
  2471.  
  2472. {
  2473.     Str255        theNumStr;        /* the number as a string */
  2474.     
  2475.     NumToString(theNum, theNumStr);
  2476.     utl_SetDialogText(theDialog, itemNo, theNumStr);
  2477. }
  2478.  
  2479. /*______________________________________________________________________
  2480.  
  2481.     utl_SetDialogPopupValue - Set Dialog Popup Control Value.
  2482.     
  2483.     Entry:    theDialog = pointer to dialog record.
  2484.                 itemNo = item number of statText or editText item.
  2485.                 val = the new string value.
  2486.                 defaultVal = the default numeric control value.
  2487. _____________________________________________________________________*/
  2488.  
  2489. void utl_SetDialogPopupValue (DialogPtr theDialog, short itemNo,
  2490.     Str255 val, short defaultVal)
  2491.     
  2492. {
  2493.     short                itemType;        /* item type */
  2494.     ControlHandle    theControl;        /* handle to control */
  2495.     Rect                box;                /* item rectangle */
  2496.     MenuHandle        theMenu;            /* handle to menu */
  2497.     short                numItems;        /* number of menu items */
  2498.     short                i;                    /* loop index */
  2499.     Str255            menuItem;        /* menu item */
  2500.     
  2501.     GetDItem(theDialog, itemNo, &itemType, (Handle*)&theControl, &box);
  2502.     theMenu = (**((popupPrivateData**)(**theControl).contrlData)).mHandle;
  2503.     numItems = CountMItems(theMenu);
  2504.     for (i = 1; i <= numItems; i++) {
  2505.         GetItem(theMenu, i, menuItem);
  2506.         if (EqualString(menuItem, val, true, true)) {
  2507.             SetCtlValue(theControl, i);
  2508.             return;
  2509.         }
  2510.     }
  2511.     SetCtlValue(theControl, defaultVal);
  2512. }
  2513.  
  2514. /*______________________________________________________________________
  2515.  
  2516.     utl_SetDialogText - Set Dialog Item Text.
  2517.     
  2518.     Entry:    theDialog = pointer to dialog record.
  2519.                 itemNo = item number of statText or editText item.
  2520.                 theText = the new text.
  2521. _____________________________________________________________________*/
  2522.  
  2523. void utl_SetDialogText (DialogPtr theDialog, short itemNo, Str255 theText)
  2524.  
  2525. {
  2526.     short        itemType;            /* item type */
  2527.     Handle    item;                    /* handle to item */
  2528.     Rect        box;                    /* item rectangle */
  2529.  
  2530.     GetDItem(theDialog, itemNo, &itemType, &item, &box);
  2531.     SetIText(item, theText);
  2532. }
  2533.  
  2534. /*______________________________________________________________________
  2535.  
  2536.     utl_SetDialogUserItem - Set Dialog User Item.
  2537.     
  2538.     Entry:    theDialog = pointer to dialog record.
  2539.                 itemNo = item number of statText or editText item.
  2540.                 userItem = pointer to user item function.
  2541. _____________________________________________________________________*/
  2542.  
  2543. void utl_SetDialogUserItem (DialogPtr theDialog, short itemNo, Handle userItem)
  2544.  
  2545. {
  2546.     short        itemType;            /* item type */
  2547.     Handle    item;                    /* handle to item */
  2548.     Rect        box;                    /* item rectangle */
  2549.  
  2550.     GetDItem(theDialog, itemNo, &itemType, &item, &box);
  2551.     SetDItem(theDialog, itemNo, itemType, userItem, &box);
  2552. }
  2553.  
  2554. /*______________________________________________________________________
  2555.  
  2556.     utl_SpinCursor - Animate cursor.
  2557.     
  2558.     After calling InitSpinCursor to initialize an animated cursor, call
  2559.     SpinCursor periodically to make the cursor animate.
  2560. _____________________________________________________________________*/
  2561.  
  2562. void utl_SpinCursor (void)
  2563.  
  2564. {
  2565.     CursHandle        h;                /* handle to cursor */
  2566.     long                ticksNow;    /* current tick count */
  2567.     
  2568.     ticksNow = TickCount();
  2569.     if (ticksNow < LastTick + TickInterval) return;
  2570.     LastTick = ticksNow;
  2571.     CurCurs++;
  2572.     if (CurCurs >= NumCurs) CurCurs = 0;
  2573.     h = CursArray[CurCurs];
  2574.     SetCursor(*h);
  2575. }
  2576.  
  2577. /*______________________________________________________________________
  2578.  
  2579.     utl_StaggerWindow - Stagger a New Window
  2580.     
  2581.     Entry:    windRect = window portrect.
  2582.                 initialOffset = intitial pixel offset of window from corner.
  2583.                 offset = offset for subsequent staggered windows.
  2584.     
  2585.     Exit:        pos = window position.
  2586.     
  2587.     According to HIN 6, a new window should be positioned as follows:
  2588.     "The first document window should be positioned in the upper-left corner
  2589.     of the gray area of the main screen (the screen with the menu bar).
  2590.     Each additional independent window should be staggered from the upper-left
  2591.     corner of the screen that contains the largest portion of the
  2592.     frontmost window."  Also, "When a window is used or closed, its original
  2593.     position becomes available again.  The next window opened should use this
  2594.     position.  Similarly, if a window is moved onto a previously available
  2595.     position, that position becomes unavailable again."
  2596.     
  2597.     This routine implements these rules.  A position is considered to be
  2598.     "unavailable" if some other window is within (offset+1)/2 pixels of the
  2599.     position in both the vertical and horizontal directions.
  2600.     
  2601.     If all slots are occupied, the routine attempts to locate the first one
  2602.     which is occupied by only one other window.  If this attempt fails, it
  2603.     tries to locate one which is occupied by only two other windows, etc.
  2604.     Thus, if the screen is filled with staggered windows, subsequent windows
  2605.     will be staggered on top of the existing ones, forming a second "layer."
  2606.     If this layer fills up, a third layer is started, etc.
  2607. _____________________________________________________________________*/
  2608.  
  2609. void utl_StaggerWindow (Rect *windRect, short initialOffset, short offset, 
  2610.     Point *pos)
  2611.  
  2612. {
  2613.     GrafPtr            savedPort;        /* saved grafport */
  2614.     short                offsetDiv2;        /* offset/2 */
  2615.     short                windHeight;        /* window height */
  2616.     short                windWidth;        /* window width */
  2617.     WindowPtr        frontWind;        /* pointer to front window */
  2618.     GDHandle            gd;                /* GDevice */
  2619.     Rect                screenRect;        /* screen rectangle */
  2620.     Rect                junkRect;        /* window rectangle */
  2621.     Boolean            hasMB;            /* true if screen has menu bar */
  2622.     Point                initPos;            /* initial staggered window position */
  2623.     Point                curPos;            /* current staggered window position */
  2624.     WindowPtr        curWind;            /* pointer to current window */
  2625.     Point                windPos;            /* current window position */
  2626.     short                deltaH;            /* horizontal distance */
  2627.     short                deltaV;            /* vertical distance */
  2628.     short                layer;            /* layer number */
  2629.     short                nOccupied;        /* number windows occupying cur pos */
  2630.     Boolean            noPos;            /* true if no position is on screen */
  2631.     
  2632.     GetPort(&savedPort);
  2633.     offsetDiv2 = (offset+1)>>1;
  2634.     windHeight = windRect->bottom - windRect->top;
  2635.     windWidth = windRect->right - windRect->left;
  2636.     frontWind = FrontWindow();
  2637.     if (frontWind) {
  2638.         utl_GetWindGD(frontWind, &gd, &screenRect, &junkRect, &hasMB);
  2639.     } else {
  2640.         screenRect = qd.screenBits.bounds;
  2641.         hasMB = true;
  2642.     }
  2643.     if (hasMB) screenRect.top += utl_GetMBarHeight();
  2644.     SetPt(&initPos, screenRect.left + initialOffset + 1, 
  2645.         screenRect.top + initialOffset + titleBarHeight);
  2646.     layer = 1;
  2647.     while (true) {
  2648.         /* Test each layer number "layer", starting with 1 and incrementing by 1.
  2649.             Break out of the loop when we find a position curPos which
  2650.             is "occupied" by fewer than "layer" other windows. */
  2651.         curPos = initPos;
  2652.         noPos = true;
  2653.         while (true) {
  2654.             /* Test each possible position curPos.  Break out of the loop
  2655.                 when we have exhaused the possible positions, or when we
  2656.                 have located one which has < layer "occupants". */
  2657.             curWind = frontWind;
  2658.             if (curPos.v + windHeight >= screenRect.bottom ||
  2659.                 curPos.h + windWidth >= screenRect.right) {
  2660.                 break;
  2661.             }
  2662.             noPos = false;
  2663.             nOccupied = 0;
  2664.             while (curWind) {
  2665.                 /* Scan the window list and count up how many of them "occupy"
  2666.                     the current location curPos.  Break out of the loop when
  2667.                     we reach the end of the list, or when the count is >=
  2668.                     layer. */
  2669.                 SetPt(&windPos, 0, 0);
  2670.                 SetPort(curWind);
  2671.                 LocalToGlobal(&windPos);
  2672.                 deltaH = curPos.h - windPos.h;
  2673.                 deltaV = curPos.v - windPos.v;
  2674.                 if (deltaH < 0) deltaH = -deltaH;
  2675.                 if (deltaV < 0) deltaV = -deltaV;
  2676.                 if (deltaH <= offsetDiv2 && deltaV <= offsetDiv2) {
  2677.                     nOccupied++;
  2678.                     if (nOccupied >= layer) break;
  2679.                 }
  2680.                 curWind = (WindowPtr)(((WindowPeek)curWind)->nextWindow);
  2681.             }
  2682.             if (!curWind) break;
  2683.             curPos.h += offset;
  2684.             curPos.v += offset;
  2685.         }
  2686.         if (!curWind || noPos) break;
  2687.         layer++;
  2688.     }
  2689.     SetPort(savedPort);
  2690.     *pos = curPos;
  2691. }
  2692.  
  2693. /*_____________________________________________________________________
  2694.  
  2695.     utl_StandardAsciiChar - Check if Character is a Standard ASCII Printable
  2696.         Character.
  2697.         
  2698.     Entry:    c = character.
  2699.     
  2700.     Exit:        Function result = true if standard ASCII printable char.
  2701. _____________________________________________________________________*/
  2702.  
  2703. Boolean utl_StandardAsciiChar (char c)
  2704.  
  2705. {
  2706.     return (c >= 0x20) && (c <= 0x7e);
  2707. }
  2708.  
  2709. /*______________________________________________________________________
  2710.  
  2711.     utl_StopAlert - Present Stop Alert
  2712.     
  2713.     Entry:    alertID = resource id of alert.
  2714.                 filterProc = pointer to filter proc.
  2715.                 cancelItem = item number of cancel button, or 0 if
  2716.                     none.
  2717.     
  2718.     Exit:        function result = item number
  2719.                 
  2720.     This routine is identical to the Dialog Manager routine StopAlert,
  2721.     except that it centers the alert on the main window, and if requested,
  2722.     Command/Period or the Escape key is treated the same as a click on the 
  2723.     Cancel button.
  2724. _____________________________________________________________________*/
  2725.  
  2726. short utl_StopAlert (short alertID, ModalFilterProcPtr filterProc,
  2727.     short cancelItem)
  2728.  
  2729. {
  2730.     GrafPtr            savedPort;    /* save grafport */
  2731.     Handle            h;                /* handle to alert resource */
  2732.     short                result;        /* function result */
  2733.     
  2734.     GetPort(&savedPort);
  2735.     InitCursor();
  2736.     h = GetResource('ALRT', alertID);
  2737.     HLock(h);
  2738.     utl_CenterDlogRect(*(Rect**)h, false);
  2739.     Filter = filterProc;
  2740.     DefaultItem = ok;
  2741.     CancelItem = cancelItem;
  2742.     IBeamHandle = GetCursor(iBeamCursor);
  2743.     result = StopAlert(alertID, MetaFilter);
  2744.     HUnlock(h);
  2745.     SetPort(savedPort);
  2746.     return result;
  2747. }
  2748.  
  2749. /*______________________________________________________________________
  2750.  
  2751.     utl_SwitchDialogRadioButton - Switch Dialog Radio Button.
  2752.     
  2753.     Entry:    theDialog = pointer to dialog record.
  2754.                 itemNo = item number of radio button to set..
  2755.                 first = item number of first radio button in group.
  2756.                 last = item number of last radio button in group.
  2757. _____________________________________________________________________*/
  2758.  
  2759. void utl_SwitchDialogRadioButton (DialogPtr theDialog, short itemNo,
  2760.     short first, short last)
  2761.  
  2762. {
  2763.     short            i;            /* loop index */
  2764.     
  2765.     for (i = first; i <= last; i++)
  2766.         utl_SetDialogControlValue(theDialog, i, 0);
  2767.     utl_SetDialogControlValue(theDialog, itemNo, 1);
  2768. }
  2769.  
  2770. /*______________________________________________________________________
  2771.  
  2772.     utl_SysHasNotMgr - Check to See if System has Notification Manager.
  2773.     
  2774.     Exit:            function result = true if system has Notification
  2775.                         Manager..
  2776.     
  2777.     The system version must be >= 6.0.
  2778. _____________________________________________________________________*/
  2779.  
  2780. Boolean utl_SysHasNotMgr (void)
  2781.  
  2782. {
  2783.     if (!GotSysEnviron) GetSysEnvirons();
  2784.     return TheWorld.systemVersion >= 0x0600;
  2785. }
  2786.  
  2787. /*______________________________________________________________________
  2788.  
  2789.     utl_SysHasPopUp - Check to See if System has Popup Menus.
  2790.     
  2791.     Exit:            function result = true if system has popup menus.
  2792.     
  2793.     The system version must be >= 4.1, the machine must have the 128 ROM or 
  2794.     later, and the PopUpMenuSelect trap must exist.
  2795. _____________________________________________________________________*/
  2796.  
  2797. Boolean utl_SysHasPopUp (void)
  2798.  
  2799. {
  2800.     if (!GotSysEnviron) GetSysEnvirons();
  2801.     if ((TheWorld.systemVersion < 0x0410) || (TheWorld.machineType == envMac)) {
  2802.         return false;
  2803.     } else {
  2804.         return NGetTrapAddress(_PopUpMenuSelect & 0x3ff, ToolTrap) !=
  2805.             NGetTrapAddress(_Unimplemented & 0x3ff, ToolTrap);
  2806.     }
  2807. }
  2808.  
  2809. /*______________________________________________________________________
  2810.  
  2811.     utl_TellMeTwiceAlert - Present Tell Me Twice Alert.
  2812.     
  2813.     Entry:    tmpl = tell me twice message template.
  2814.                 dlogID = resource id of tell me twice message dialog.
  2815.                 filterProc = pointer to filter proc.
  2816.                 p0,p1,p2,p3 = parameters to plug into template.
  2817.                 
  2818.     Exit:        function result = item number of button selected.
  2819.                 
  2820.     The tell me twice dialog must have:
  2821.     item 1 = Doit button.
  2822.     item 2 = Cancel button.
  2823.     item 3 = stop icon.
  2824.     item 4 = static text field with content "^0".
  2825.     item 5 = user item used to outline the OK button.
  2826.     
  2827.     This function adjusts the height of the alert and the static text
  2828.     field so that they are just high enough to contain the message.
  2829. _____________________________________________________________________*/
  2830.  
  2831. short utl_TellMeTwiceAlert (Str255 tmpl, short dlogID, 
  2832.     ModalFilterProcPtr filterProc, Str255 p0, Str255 p1,
  2833.     Str255 p2, Str255 p3)
  2834.  
  2835. {
  2836.     return MagicAlert(tmpl, dlogID, filterProc, p0, p1, p2, p3, 2, 4, 5, 1, 2);
  2837. }
  2838.  
  2839. /*______________________________________________________________________
  2840.  
  2841.     utl_TellMeTwiceAlertRez - Present Tell Me Twice Alert.
  2842.     
  2843.     Entry:    rezID = resource id of STR# resource containing message
  2844.                     template.
  2845.                 index = index in STR# resource of message template.
  2846.                 dlogID = resource id of dialog.
  2847.                 filterProc = pointer to filter proc.
  2848.                 p0, p1, p2, p3 = parameters to plug into template.
  2849.                 
  2850.     Exit:        function result = item number of button selected.
  2851. _____________________________________________________________________*/
  2852.  
  2853. short utl_TellMeTwiceAlertRez (short rezID, short index, short dlogID,
  2854.     ModalFilterProcPtr filterProc, 
  2855.     Str255 p0, Str255 p1, Str255 p2, Str255 p3)
  2856.     
  2857. {
  2858.     Str255            tmpl;            /* message template */
  2859.     
  2860.     GetIndString(tmpl, rezID, index);
  2861.     return utl_TellMeTwiceAlert(tmpl, dlogID, filterProc, p0, p1, p2, p3);
  2862. }
  2863.  
  2864. /*______________________________________________________________________
  2865.  
  2866.     utl_ToggleDialogCheckBox - Toggle a dialog checkbox control.
  2867.     
  2868.     Entry:    theDialog = pointer to dialog record.
  2869.                 itemNo = item number of statText or editText item.
  2870.                 
  2871.     Exit:        function result = new control value (0=off, 1=on).
  2872. _____________________________________________________________________*/
  2873.  
  2874. short utl_ToggleDialogCheckBox (DialogPtr theDialog, short itemNo)
  2875.  
  2876. {
  2877.     short            newVal;        /* new value of checkbox control */
  2878.  
  2879.     newVal = 1 - utl_GetDialogControlValue(theDialog, itemNo);
  2880.     utl_SetDialogControlValue(theDialog, itemNo, newVal);
  2881.     return newVal;
  2882. }
  2883.  
  2884. /*______________________________________________________________________
  2885.  
  2886.     utl_VolIsMFS - Test for MFS volume.
  2887.     
  2888.     Entry:    vRefNum = volume reference number.
  2889.     
  2890.     Exit:        function result = true if volume is MFS.
  2891. _____________________________________________________________________*/
  2892.  
  2893. Boolean utl_VolIsMFS (short vRefNum)
  2894.  
  2895. {
  2896.     HParamBlockRec        vBlock;            /* vol info param block */
  2897.     
  2898.     vBlock.volumeParam.ioNamePtr = nil;
  2899.     vBlock.volumeParam.ioVolIndex = 0;
  2900.     vBlock.volumeParam.ioVRefNum = vRefNum;
  2901.     vBlock.volumeParam.ioVSigWord = 0xd2d7;    /* in case we don't have HFS */
  2902.     (void) PBHGetVInfo(&vBlock, false);
  2903.     return vBlock.volumeParam.ioVSigWord == 0xd2d7;
  2904. }
  2905.  
  2906. /*______________________________________________________________________
  2907.  
  2908.     utl_WaitNextEvent - Get Next Event.
  2909.     
  2910.     Entry:    eventMask = event mask.
  2911.                 sleep = sleep interval.
  2912.                 mouseRgn = mouse region.
  2913.     
  2914.     Exit:        theEvent = the next event.
  2915.                 function result = true if event to be processed.
  2916.                 
  2917.     This routine calls WaitNextEvent if the trap exists, otherwise it
  2918.     calls GetNextEvent.  
  2919.     
  2920.     If GetNextEvent is called, the sleep and mouseRgn parameters are 
  2921.     ignored.  SystemTask is also called.
  2922.                 
  2923.     This routine also saves and restores the current grafport.  This is
  2924.     necessary to protect against some GetNextEvent trap patches which change
  2925.     the grafport without restoring it (e.g., the Flex screen saver).
  2926. _____________________________________________________________________*/
  2927.  
  2928. Boolean utl_WaitNextEvent (short eventMask, EventRecord *theEvent,
  2929.     long sleep, RgnHandle mouseRgn)
  2930.  
  2931. {
  2932.     GrafPtr            curPort;        /* pointer to current grafport */
  2933.     Boolean            result;        /* function result */
  2934.     static short    wne = 2;        /* 0 if WaitNextEvent does not exist
  2935.                                             1 if WaitNextEvent exists
  2936.                                             2 if we don't yet know (first call) */
  2937.     
  2938.     /* Find out whether the WaitNextEvent trap is implemented if this is 
  2939.         the first call. */
  2940.     
  2941.     if (wne == 2) {
  2942.         if (!GotSysEnviron) GetSysEnvirons();
  2943.         if (TheWorld.machineType < 0) {
  2944.             wne = false;
  2945.         } else {
  2946.             wne = (NGetTrapAddress(_WaitNextEvent & 0x3ff, ToolTrap) == 
  2947.                 NGetTrapAddress(_Unimplemented & 0x3ff, ToolTrap)) ? 0 : 1;
  2948.         }
  2949.     }
  2950.     
  2951.     /* Save the port, call the trap, and restore the port. */
  2952.     
  2953.     GetPort(&curPort);
  2954.     if (wne) {
  2955.         result = WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
  2956.     } else {
  2957.         SystemTask();
  2958.         result = GetNextEvent(eventMask, theEvent);
  2959.     }
  2960.     SetPort(curPort);
  2961.     return result;
  2962. }
  2963.